Release notes for 2022¶
All notable changes in reverse chronological order.
Version 1.8.2 (3 Dec, 2022)¶
- Implemented methods for plotting trades as signals - EntryTrades.plot_signals, ExitTrades.plot_signals, and Portfolio.plot_trade_signals
- Implemented a method for plotting ranges as shapes - Ranges.plot_shapes
- Fixed creation of three-dimensional
splits_arrin Splitter, now the array will always be two-dimensional and have the data typeobject - Added support for timestamps and timedeltas in Splitter
- Fixed Trades.get_edge_ratio and Trades.get_running_edge_ratio when
highand/orloware not provided; in this case, rolling volatility instead of ATR will be used. - Method Splitter.plot_coverage will return a stacked area plot by default
- Implemented a method Splitter.get_overlap_matrix for calculation of an overlapping coverage matrix
- Implemented a method GenericAccessor.proximity_apply for rolling and reducing a two-dimensional window of neighboring elements
- Refactored ArrayWrapper.indexing_func_meta to make indexing operations on vectorbt objects more flexible and efficient
- Enabled row stacking in Splitter.take
- Implemented methods Splitter.shuffle_splits and Splitter.break_up_splits for shuffling and breaking up splits respectively
- Fixed bound attachment in Splitter.take and Splitter.apply
- The method Data.run can now run multiple indicators by passing a sequence, and even all indicators by adding the suffix
_allto a library name, and stack outputs along columns into a single DataFrame - The simulation method Portfolio.from_holding is now cached by default (use
dynamic_mode=Trueto use a signal function) - Made the method ReturnsAccessor.deflated_sharpe_ratio more robust to invalid Sharpe values (
np.nanandnp.inf) - Implemented a method for calculating the Probabilistic Sharpe Ratio - ReturnsAccessor.prob_sharpe_ratio
- Wrote Cross validation
Version 1.8.1 (15 Nov, 2022)¶
- Fixed an error in pattern fitting when
max_error_interp_modeis not set - Data dictionary can be constructed from data keyed by feature instead of symbol, which can enabled using the argument
columns_are_symbols - Replaced an argument name
stretchin favor ofextendin projection context - Implemented a decorator for splitting - @split
- Implemented a decorator for cross-validated splitting - @cv_split
- Fixed formatting of auto-generated record attributes
- Parameters of the type Param can conditionally depend on other parameters. For example,
param1 > param2will select only the parameter combinations where the value of the first parameter is greater than that of the second parameter. - Iterative portfolio Numba-compiled functions can override
i,col, andflex_2dprovided via the context - Fixed exit signal generation with
skip_until_exit - Implemented Edge Ratio in Trades
- Introduced a one-to-one mapping between orders and trades: each trade record includes the ID of the order that opened and closed the trade (not the other way around)
- Implemented a method Portfolio.get_trade_history, which merges orders and trades and returns the information as a human-readable DataFrame
- TVData has got an update method
- Implemented squeezing of splits and sets in Splitter.take and Splitter.apply
- Implemented a splitter class method (Splitter.from_grouper) that can build a splitter based on grouping/resampling with vectorbt or Pandas (for example, "M" for monthly periodicity)
- Each ArrayWrapper and Wrapping instance has a convenient method
split - Updated the notebooks that used outdated splitting API
Version 1.8.0 (24 Oct, 2022)¶
- Created an accessor for Pandas Indexes, BaseIDXAccessor. Migrated some index-related functionality from ArrayWrapper such as BaseIDXAccessor.get_grouper. Also, created methods for many functions from the base.indexes module.
- Added
clear_cacheandcollect_garbagearguments to SerialEngine, such that it can clear the cache and collect the garbage (globally) after each iteration - Implemented a method for preparing returns (prepare_returns). The function riskfolio_optimize now prepares the returns automatically (for example, it can remove columns that are all NaN or zero).
- Implemented a base module for merging arrays - base.merging. Also, unified merging functionality across the @parameterized and @chunked decorators.
- Added two new execution engines: ThreadPoolEngine and ProcessPoolEngine, which are lightweight alternatives to Dask and Ray respectively
- Fixed an issue where using the Plotly Express accessor raised an error
- Implemented a method for fitting a pattern GenericSRAccessor.fit_pattern
- Updated TVData to
tvdatafeed>=2.1.0 - Made vectorbt load much faster by outsourcing import statements to the functions that actually need them. Auto-import of many optional functionalities can now be controlled from settings.importing, disabling all options brings the loading time to around one second and half.
- Fixed an issue where selecting a date range from a signal portfolio raised an error
- Fixed PolygonData
- Implemented a new signal detection indicator, SIGDET (see https://stackoverflow.com/a/22640362)
- Fixed many potential division by zero conditions in records
- Fixed the calculation of gross exposure for short positions
- Redesigned accessors to take an array wrapper as the first argument and accept arbitrary array-like objects
- Implemented Splitter
Version 1.7.1 (23 Sep, 2022)¶
- Data stored before
1.7.0can be unpicked again after this release. Made pickled vectorbt objects more resistant to API changes. - Fixed wrong
min_sizeandmax_sizedefaults - Fixed division by zero in the VIDYA indicator
- Merged
ZIGZAGindicator into PIVOTINFO - Plotting accessor methods now also accept DataFrames with the ability to select a column to plot
- Added the streaming SUPERTREND indicator from the tutorial
- Added the streaming ReturnsAccessor.rolling_sharpe_ratio method from the tutorial
- Removed
applyandcustomprefixes from the Numba-compiled indicator functions. Also added chunking specifications.
Version 1.7.0 (20 Sep, 2022)¶
- Implemented a portfolio method (and its corresponding property) for calculating real allocations - Portfolio.get_allocations
- Implemented a portfolio method (and its corresponding property) for calculating asset PnL, which is similar to asset returns but in notional terms - Portfolio.get_asset_pnl
- Fixed asset returns being improperly calculated when position is being reversed
- Improved plotting of allocations in PortfolioOptimizer such that there are no more diagonal lines, looks like bars but takes considerably less time to draw
- Implemented (NB and SP) VIDYA and made it available as a window type in custom indicators
- CCXTData has got a class method to find the earliest date of any symbol on any exchange. Gets called automatically.
- Lifted the limitation of merging only different symbols. If two data instances have the same symbols, their dataframes will be merged across rows and columns.
- Extended
ConflictMode.Oppositeto issue an entry signal when not in position - Added some convenience methods to custom data classes. For example, instead of calling
DataClass.set_settings(path_id="custom", ...)to change the settings of any class globally, we can simply callDataClass.set_custom_settings(...). Also, there are new methods RemoteData.from_csv and RemoteData.from_hdf that pull data from a CSV and HDF file respectively, and set up the class. This is a better alternative to using local data classes when data updates are wanted. - Enabled random search in indicators by introducing an argument
random_subset, which selects a subset of parameter combinations randomly - Integrated the freqtrade's technical library as both technical indicators (
vbt.technical(...)) and consensus indicators (vbt.techcon(...)) - Kaleido is now one of the optional dependencies
- Implemented a ZIGZAG indicator, inspired by the following implementation: https://github.com/jbn/ZigZag (best used for plotting, note that the first pivot is computed by looking into the future!)
- Implemented a PIVOTINFO indicator, which has a similar implementation but is look-ahead bias resistant and contains lots of useful information such as the last confirmed pivot type, index, and value, but also the most recent (not confirmed yet) pivot type, index, and value.
- Added global options (available under settings.wrapping with the prefix
prec_) to set a minimum and maximum integer and floating precision of wrapped arrays. Depending on the platform, Numba mostly returns 64-bit numbers. When those arrays are wrapped with Pandas using ArrayWrapper.wrap, vectorbt can cast them to 32 bits or lower to save memory. Note that Numba does not support 16-bit numbers (yet), but we can still use them with Pandas. - Implemented an accessor method GenericSRAccessor.to_renko that converts any time series into the Renko format. Note that Renko data may contain irregular, duplicate datetime index, and shouldn't be used for anything that requires a frequency (such as Sharpe).
- Order arguments
min_sizeandmax_sizenow depend onsize_type. For example, specifyingmin_sizeof 10% whensize_typeisSizeType.TargetPercentwon't execute the order if the requested order size is less than 10% of the current portfolio value. - Profit factor, expectancy, and SQN can be also computed from returns rather than PnL (see the respective Trades property but with the prefix
rel_) - Implemented a decorator @parameterized, which can wrap any Python function and parameterize its inputs either with Param or with special parameter configs. This way, even though the original function can process only one combination of parameters at a time, the wrapped function looks the same from the outside but can handle unlimited number of combinations!
- Class methods PortfolioOptimizer.from_allocate_func and PortfolioOptimizer.from_optimize_func were completely refactored and are now based on parameters (similar workings to the @parameterized decorator)
- Argument
product_idxin Param and BCO was renamed tolevel - Added support for symbol classes in Data. They can be specified when fetching using
classes. Upon preparing the data, one or more column levels will be created. Useful for attaching information on industries, sectors, and other asset classes. - Integrated Riskfolio-Lib in a similar fashion as PyPortfolioOpt: there is now a function riskfolio_optimize and an infrastructure around it to run arbitrary optimization models from Riskfolio-Lib with a single function call. Rebalancing is done by PortfolioOptimizer.from_riskfolio.
- Fixed the incompatibility issue between NumPy and TA-Lib in the Dockerfile. Also, included the installation of universal-portfolios.
- Lifted the limit of 10k fetched data points in AlpacaData
- Implemented a method
list_symbolsfor a range of local and remote data classes to get the list of all available symbols (and automatically filter it using regular expressions and other conditions) - Updated Portfolio optimization
- Wrote Stop signals
Version 1.6.1 (20 Aug, 2022)¶
- Scheduler accepts two new arguments:
zero_offsetandforce_missed_run - Migrated the website to another private repository to respect separation of concerns
- Website is now divided into a public part and a private part (for members only). Most documentation and API documentation have been made exclusive. Added a new getting started guide for members. Each documentation and tutorial page can be auto-converted into a Python code.
Version 1.6.0 (15 Aug, 2022)¶
- Fixed conversion of datetime indexes into nanosecond format on Windows by replacing
np.int_tonp.int64. In addition, implemented the methods Wrapping.ns_index, Wrapping.get_period_ns_index, and Wrapping.ns_freq that do this automatically. - Added missing layout keyword arguments to GenericSRAccessor.plot_pattern
- Unified the timeframe format across the entire codebase, including custom data classes. This allows for passing human-readable strings such as "15 minutes".
- Switched the third-party package of AlpacaData from the outdated
alpaca-trade-api-pythonto the newestalpaca-py - Added configuration examples under the API documentation of each custom data class
- Added functionality for the configured classes to talk to their globally defined settings, which includes the methods Configured.get_settings, Configured.set_settings, and Configured.reset_settings. The key pointing towards the global settings is stored in the class variable
_settings_key. This allows to seamlessly change the settings of custom data classes, for example. - Fixed forced import of dill
- Enabled using mappings in MappedArray.to_pd
- Renamed the default key
_defaultto_defeverywhere (BCO instances, index dictionaries, etc.) - Fixed getting the duration of range-like records when the index is not datetime-like
- Orders has got two new fields:
signed_sizeandvalue - Refactored iterative helper functions for portfolio. For instance,
get_elem_nbhas been renamed toselect_nb. Added iterative above and crossover functions. All such functions have been put into the module portfolio.nb.iter_. - Implemented iterative above and crossover functions in generic.nb.iter_
- Added methods Data.switch_class and Data.update_fetch_kwargs to switch between data classes more easily
- Fixed the Basic RSI tutorial, documentation, and label generators to use the newest
wtypeargument - Changed the default start value for cumulative returns from 0 to 1
- Refactored Portfolio.from_signals once again:
- Renamed
StopExitModeandupon_stop_exittoStopExitTypeandstop_exit_typerespectively - Renamed the suffix of index fields in limit and stop order records from
itoidx - Added exit price, exit type, and order type to stop order records. The information is now being pulled from the entry point rather than exit point!
- Disabled bound checking globally as the vectorbt's functionality has been thoroughly tested. You can still add
boundscheck=Trueto the@njitdecorator to enable bound checking in your function. - In-outputs in the flexible mode are now being handled the same as in Portfolio.from_order_func. Argument
fill_returnshas been disabled for that mode. - Delayed the resolution of the arguments
limit_tifandlimit_expiryto after broadcasting - Simulation iterates in the group-major order in the flexible mode regardless of cash sharing
- Argument
stop_exit_pricecan take a custom price - In a group with cash sharing, orders are additionally sorted by bar zone if automatic call sequence is disabled
- Added a variety of convenient functions for working in callbacks, such as set_limit_info_nb
- Groups are now being valuated strictly using the valuation price (which is mostly the opening price) to avoid the look-ahead bias when working with limit and stop orders
- Fixed the scenario where the valuation price was set to the order price in limit and stop orders
- Renamed
- Added a convenient function
vbt.clear_pycache()to clear the cache of the entire package - Added Python 3.10 support
- Wrote documentation on From signals
Version 1.5.0 (29 Jul, 2022)¶
- Implemented from_signals_nb, which is a cached version that gets used automatically by Portfolio.from_signals if none of the
adjust_func_nb,signal_func_nb, andpost_segment_func_nbwere provided. This way, we can avoid repeated compilation in each new runtime. - Added a post-segment function to Portfolio.from_signals. It can be used, for example, for pre-computing custom metrics during the simulation.
- Created the method Records.prepare_customdata, which prepares custom data to be showed when hovering over a Plotly trace, given only the options specified in the field config. This method is utilized in all record classes, such as Trades, so the user can subclass them, define their own custom fields, and they will be displayed on hover automatically.
- Implemented numerous functions and classes for pattern detection:
- NB function interp_resize_1d_nb for interpolating values of an array
- NB function pattern_similarity_nb for calculating the similarity score between two arrays
- NB function rolling_pattern_similarity_nb and accessor method GenericAccessor.rolling_pattern_similarity for calculating the rolling similarity score between two arrays
- NB function find_pattern_nb for searching and storing patterns as range records
- Class PatternRanges for holding, analyzing, and plotting the results of one to multiple pattern searches
- Method PatternRanges.from_pattern_search as a parameterizable interface to find_pattern_nb that wraps the filled range records with PatternRanges. Works similarly to an indicator.
- Indicator PATSIM based on rolling_pattern_similarity_nb
- Implemented numerous functions for projections:
- NB function map_ranges_to_projections_nb and method Ranges.get_projections for mapping (the price during) ranges of any type to projections
- Accessor method GenericDFAccessor.plot_projections for plotting projections from any DataFrame
- Method Ranges.plot_projections for generating and plotting projections using the two methods above
- Implemented an NB function get_ranges_from_delta_nb, the class method Ranges.from_delta, and the instance method Ranges.with_delta to map records/mapped arrays/index arrays to ranges of the type Ranges that start at a specific index and last a specific duration. Useful for converting pattern ranges to be able to build projections.
- Added the argument
klines_typeto BinanceData to be able to fetch futures data - Implemented an indicator VWAP for calculating VWAP with any frequency-like anchor (daily by default)
- Refactored custom indicators and their plotting methods:
- Removed the argument
ewmin favor of the enumerated argumentwtype(window type) of the type WType, which allows the moving average and standard deviation to be computed using the new NB functions ma_nb and msd_nb respectively - Renamed
MSTDtoMSD(Moving Standard Deviation) - Enumerated types are displayed in the column hierarchy using their field names
- Switched RSI to the Wilder's moving average by default and reimplemented its NB function to be SP
- Reimplemented STOCH to return fast %K, slow %K, and slow %D
- Switched MACD to the exponential moving average by default
- Removed the argument
- The functionality to combine parameters has been outsourced from broadcast to combine_params, and generalized. It can be used by the user to parameterize any function by accepting instances of Param, as it's done by PatternRanges.from_pattern_search. Additionally, Param instances can now be passed to broadcast.
- Implemented a method Data.run, which takes a function or the name of an indicator (all third-party indicators supported), automatically recognizes what features the function accepts (for example,
closeandvolume), and runs the indicator on that features. This way we can run indicators quickly, as there is no need more to manually search for input names. - Drawdowns can now be built from OHLC data, not only close
- ArrayWrapper.wrap supports complex broadcasting
- Disabled Plotly resampler globally (can be enabled in settings) as it doesn't fit all graphs
- Enabled bound checking globally (can be disabled in settings) as it makes finding indexing errors easier for the user while making the execution just a bit slower
- Various record classes allow to be converted into Ranges for range analysis. For example, the class Drawdowns has the method Drawdowns.get_recovery_ranges and the auto-generated property
recovery_rangesto build ranges between the valley point and the recovery point. - Created methods for getting a number of the first (Records.first_n), last (Records.last_n), and random (Records.random_n) records
- Improved formatting of dicts and configs in the API documentation
- Added flags such as
plot_closeto disable plotting of various traces in ranges, drawdowns, orders, and trades - Wrote Patterns and projections
Version 1.4.2 (28 Jun, 2022)¶
- Integrated plotly-resampler. If installed, resampled figures/widgets will be used automatically. If not, will fall back to regular Plotly figures/widgets. Can be force-enabled or disabled in the global settings. Only scatter traces are supported.
- Hit detection of limit order price in Portfolio.from_signals can be reversed using the argument
limit_reverse - Previously, not expected arguments that were passed to any class method were "swallowed" by the class. Now, passing such arguments will raise an error. No more mistyping arguments!
- Created a Dockerfile that runs JupyterLab and includes VBT and most of its optional dependencies
Version 1.4.1 (25 Jun, 2022)¶
- Fixed error when providing any stop in Portfolio.from_signals as an index or a BCO instance
- Added new argument
from_agoto Portfolio.from_orders and Portfolio.from_signals, which controls how many bars ago the order information should be taken from. This feature can be used instead of shifting arrays manually. For example, settingfrom_ago=1will shift order information by one bar and thus execute using the next close by default. - PriceType has been extended and
pricecan now be provided asnextopenandnextclose, which will setfrom_agoto 1 automatically. Those types cannot be used as part of arrays. - Limit signals, stop signals, and user signals in Portfolio.from_signals can be better distinguished where exactly in a bar they execute. Limit signals can be executed at open and in the middle of the bar. Stop signals can be executed at open, in the middle of the bar, or postponed to close. User signals can be executed at open, in the middle of the bar, and at close. Knowing this allows us to build an accurate execution chain that respects the timing of each signal.
Version 1.4.0 (21 Jun, 2022)¶
- Completely refactored Portfolio.from_signals:
- Signal function
signal_func_nbtakes the context SignalContext with much more useful information than previously. User-defined arguments are not included in the context but you can always forward them to the function using templates. - Preset signal functions take as argument an adjustment function
adjust_func_nbthat allows changing any current information prior to returning the signals, which is especially useful for adjusting limits and stops - When there is no signal in any of the columns of a group, the group won't be executed, which results in a great speedup for sparsely-distributed signals
- Stop loss has been split into two separate stop orders: SL (
sl_stop) and TSL (tsl_stop) - TTP has been integrated into TSL by adding a threshold option (
tsl_th) - Added an option for specifying the format of any delta (
delta_formatof type DeltaFormat), which makes possible providing stop values in absolute terms - Information on each stop order is now stored in one record array - one record per column, not separate arrays. For example, stop loss information is represented by a record array of data type sl_info_dt.
- Added limit order support. Whenever a signal of the limit order type is placed, it's first checked against the current bar information (OHLC if signal was placed at open, only C otherwise). It's then stored in a record array of type limit_info_dt that gets propagated throughout time and checked whether the limit has been hit or expired at each bar. Only one active limit order is allowed at a time.
- Similarly to stop orders, a limit delta can be specified to represent a distance between the initial price (
price) and the target price. For example, a delta of 0.1 will place a limit order with the target price of 10% above/below the initial price when selling/buying. - Limit orders can expire after a time delta (
limit_tif) or at a specific time (limit_expiry). The format of both is controlled bytime_delta_formatof type TimeDeltaFormat. If the format is based on index, time deltas and expiry times will be converted into integer, nanosecond format. If the input is a timedelta/datetime-like Series/DataFrame, the pre-processing will remove the timezone and convert to integer format automatically. - Previously, stop orders were pure market orders. Now, they can create a limit order once their stop has been hit. They also have their own limit delta.
- Added options for resolving conflicts between executable and pending signals. For example, providing
upon_opp_limit_conflict="cancelexecute"will cancel any pending limit order and execute the user-defined signal if it's sign is opposite to the limit order's sign. The same for pending stop orders, which can be cancelled by executable limit/user signals. - Order records generated by Portfolio.from_signals were extended with the timestamp of signal (
signal_idx), timestamp of (stop/limit) order creation (creation_idx), order type (type), and stop type (stop_type). The new data type is fs_order_dt. The new order type can be analyzed using FSOrders, which is a subclass of Orders. Other simulation methods, such as Portfolio.from_orders, still generate records of the type order_dt.
- Signal function
- Portfolio allows providing custom record classes. For example, one can create a custom subclass of Trades and pass it as
trades_clsfor portfolio to use it by default. - Added
ValuePercent- a new size type for ordering a percentage of the current group value. But also,Percent,ValuePercent, andTargetPercenthave alternatives for provision of percentages in a human-readable format (1.0 = 1%). - Instead of passing
-np.infornp.infas order/valuation price to represent open/latest and close/price, enumerated values PriceType/ ValPriceType can be used. For example, to specify that the opening price should be used as order price, passprice="open". - QSAdapter will also remove the timezone from benchmark returns, and will force the user to select one column (by offering a
columnargument) since quantstats can use only one benchmark column at a time. - OHLC chart (OHLCVDFAccessor.plot) has been updated to match the style of TradingView
- Specifying the filename when saving or loading any vectorbt object is no longer necessary - vectorbt will use the class name by default
- Fixed the situation where chunking lots of parameter combinations resulted in a progressive slowdown
- Fixed handling of input arrays of the data type
float32in generic NB functions - Implemented TVData, which wraps tvdatafeed
- Removed the "Close time" column from any DataFrame returned by Binance
Version 1.3.0 (4 Jun, 2022)¶
- Added default resamplers for trade count and VWAP in Data and resamplers for stock splits, dividends, and other columns in custom data classes
- Fixed resampling of the open price with NaN values
- Improved data type handling when wrapping, which previously threw an error when trying to cast a floating array with NaN values to an integer data type. Data type is now being cast softly.
- Fixed the implementation of VWAP: the indicator now resets with each day or any custom frequency
- Implemented a method ArrayWrapper.get_index_grouper, which similarly to ArrayWrapper.get_resampler can be passed to any accelerated method in vectorbt that makes use of row grouping
- Added the ability to generate log returns and daily returns (or both) along with simple returns, such as by using
pf.get_returns(log_returns=True). Also, every metric in ReturnsAccessor can natively work on log returns. Since the accessor cannot identify whether the passed return series is simple or log, passing the flaglog_returns=Trueis required, which is done automatically by Portfolio. For instance, to get the accessor with log returns, usepf.get_returns_acc(log_returns=True). To use log/daily returns in portfolio stats, define the corresponding flag in thesettingsdictionary. - Implemented NB and SP rolling linear regression using OLS (GenericAccessor.rolling_linreg) that returns two arrays: slope and intercept. The implemented algorithm can be used in cointegration tests and is 1100x faster than RollingOLS
- Implemented two new indicators:
- Added
minpargument to all custom indicators - Updated PolygonData for
polygon==1.0.0 - Implemented row (Wrapping.row_stack) and column (Wrapping.column_stack) stacking for vectorbt objects of arbitrary complexity. Since every vectorbt object wraps a bunch of arrays, multiple objects can be effectively merged by stacking their arrays stored internally and unifying other input information. Under the hood, the stacking first takes place between wrappers of all objects using ArrayWrapper.row_stack and ArrayWrapper.column_stack. While some objects can be stacked easily, such as ReturnsAccessor, stacking records and portfolios is a complex process and requires some assumptions to be made (see the corresponding methods).
- Refactored the indexing mechanism in ArrayWrapper to also return slices whenever possible (because data can be selected faster using slices than index arrays).
- Lifted the limitation of objects combined together being required to have the same index! Previously, an error was thrown as soon as one of the objects had a different index. Now, similarly to how Pandas does it, indexes of all objects are aligned using a "union" set operation and missing values are set to NaN or any other user-defined value specified in
reindex_kwargs. Additionally, each broadcastable argument in all the simulation methods of Portfolio, such assizein Portfolio.from_orders, have sensible fill values. - Fixed axis labels in the Volume widget
- Changed the representation of index ranges from one two-dimensional array to a tuple of one-dimensional arrays, which are easier to manage
- Deprecated pytz, now using zoneinfo
- Implemented an entirely new way of creating arrays using index dictionaries. Instead of building an array and setting its data manually, index dictionaries allow providing row and column information as keys and data as values. The function get_indices converts each key of such a dictionary into integer indices, while the method ArrayWrapper.fill_and_set sets the corresponding values at those indices by taking into account flexible indexing requirements. This makes it almost too easy to provide data such as order size at specific timestamps or even time intervals. For example, to deposit $100 monthly, provide the following to Portfolio.from_signals:
cash_deposits=vbt.index_dict({vbt.pointidx(every="M"): 100})(see the base.indexing module). Also, all arguments passed to the broadcaster can be passed as templates to be created using the final shape instead of taking part in actual broadcasting. This means, passing the following to Portfolio.from_signals or any other method now works:size=vbt.RepEval("size = wrapper.fill(); size.iloc[0] = np.inf; size"), which waits until all other arrays were successfully broadcast and the final wrapper was built, and only then creates an array and fills the first row withnp.inf. - Enabled row selection in all vectorbt objects except ColumnMapper. In objects with complex data, such as records and portfolios, only slices (that is, non-interrupting ranges) are allowed. For example, selecting a date range from a portfolio means taking the last cash, position, and close prior to the first point in the new slice, and using them as
init_cash,init_position, andinit_pricerespectively. - Made every simulation method in Portfolio accept an instance of Data as
close. Open, high, low, and close price series will be extracted automatically. - Portfolio now stores and makes use of OHLC data. Moreover, all records from Ranges to Logs also take OHLC data by subclassing a new class PriceRecords.
- Implemented MFE and MAE metrics and plots in Trades
- Fixed Portfolio.from_holding, which previously set the entry signal at the first timestamp, but since not all assets may start from the first timestamp, the entry signal may be ignored. Now, the entry signal is set dynamically using a signal function whenever a new valid value in
closeis encountered. - Optimized indexer in ArrayWrapper.get_index_points and ArrayWrapper.get_index_ranges by adding
indexer_toleranceargument to the first method and removingindexer_methodargument from the second method
Version 1.2.3 (7 May, 2022)¶
- Fixed marker color in OHLCVDFAccessor.plot when one of the price points is NaN
- Ordering in the long-only direction from a short position and short-only direction from a long position is now allowed
- Fixed output parsing in IndicatorFactory.from_expr
- Renamed
plot_as_entry_markersto SignalsSRAccessor.plot_as_entries andplot_as_exit_markersto SignalsSRAccessor.plot_as_exits. Created two more methods for marking entries (SignalsSRAccessor.plot_as_entry_marks) and exits (SignalsSRAccessor.plot_as_exit_marks). - Rolling apply can now run on variable, frequency-based windows, such as
7d - Implemented BaseAccessor.ago for getting the values some periods ago
- Implemented NB and SP rolling "any" (GenericAccessor.rolling_any) and "all" (GenericAccessor.rolling_all)
- Updated the MTF tutorial with a section on forward filling
- Indicator parameters can now be manually mapped to an index level using
post_index_funcspecified inparam_settings - Complex objects are now counted per type rather than based on their position in param_to_index
- Implemented an entire module utils.datetime_nb with Numba-compiled functions for operations on (mostly integer-formatted) date and time
- Added contexts GenEnContext, GenExContext, and GenEnExContext to signal generation functions
- Signal placement functions are now forced to return the local position of the last placed signal to make the generation (a lot) faster
- Completely refactored SignalsAccessor.generate_stop_exits to accept the inputs
entry_tsandfollow_ts, and write the in-outputstop_ts_out. This enables far more options in generating uni-directional stops. - Completely refactored SignalsAccessor.generate_ohlc_exits to separate the entry price (
entry_price) from the open price (open), and to better represent and be able to simultaneously process 4 different stop types: SL, TSL, TP, and TTP (new). Also, updated the enum StopType according to the new stop types. - Refactored ranking. Added the argument
after_resetto SignalsAccessor.rank_nb to be able to remove any signal that comes before the first resetting signal. Added the argumentreset_waitto postpone resetting the position by a number of ticks. Removedprepare_funcin favor of templates. Also made the function contextualized by adding the context RankContext with lots of useful information. - Implemented after-reset versions for various signal selection functions, such as SignalsAccessor.first_after for SignalsAccessor.first. Also, implemented the method SignalsAccessor.to_nth to select the first
nsignals. - Accessor methods in GenericAccessor that accept a UDF now also accept the name of any UDF from generic.nb
- Fixed casting the column "Trade count" to the integer data type in custom data classes
- By enabling the
parse_indexflag in settings.datetime, any index with human-readable datetime strings passed to an array wrapper will be automatically parsed and converted to a Pandas index - Added time components to the methods ArrayWrapper.get_index_points and ArrayWrapper.get_index_ranges. This, for example, allows signals to be placed and portfolios to be optimized during specific times of the day.
- Reimplemented the method SignalsAccessor.clean to take the arguments
force_first,keep_conflicts, andreverse_orderfor a better control of the cleaning process. - Implemented a method Data.transform to transform the underlying data with a UDF and replace the instance
- Wrote Signal development
Version 1.2.2 (21 Apr, 2022)¶
- Made the call sequence array entirely optional. Prior to this change, the user had to create an array of the same size as the target shape, which is pretty unnecessary and consumes lots of memory. Now, setting
call_seqto None orautowon't require a user-defined array anymore, and only the call sequence for the current row is being kept in memory. - The close price in Portfolio won't broadcast to the full shape anymore. Since all methods deploy flexible indexing, there is no need to expand and materialize the close price. Instead, it keeps its original shape while the broadcasting operation returns a wrapper that holds the target shape and other Pandas metadata. This has one big advantage: lower memory footprint.
- Disabled
flex_2deverywhere for more consistency across the codebase. Passing one-dimensional arrays will treat them per-row by default. - Fixed the shape in the wrapper returned by broadcast
- When specifying enum fields such as "targetamount", the mapper will ignore all non-alphanumeric characters by default, thus "Target Amount" can now be passed as well
- Added the option
incl_docto show/hide the docstring of the function when using phelp - ArrayWrapper.wrap will broadcast the to-be-wrapped array using NumPy rules if its shape doesn't match the shape of the wrapper. This way, smaller arrays can expand to the target shape once this is really required - good for memory.
- Added the option
indexer_methodto specify the indexer method in BaseAccessor.set and BaseAccessor.set_between to control which timestamp (previous or next?) should be used if there is no exact match - Cash deposits and cash earnings now respect the cash balance in Portfolio.from_orders and Portfolio.from_signals. But also, cash deposits now behave the same way as cash earnings: a full array will be created during the simulation if any element of the passed cash deposits is not zero; this array will be overridden in-place at each row and group, and then returned as a part of the simulation output.
- Added the option
skipnain Portfolio.from_orders for skipping rows where the size in all columns of a group is NaN - Wrote documentation on From orders
Version 1.2.1 (10 Apr, 2022)¶
- Fixed check for zero size in buy_nb
- Fixed is_numba_func when Numba is disabled globally
- Use record counts (
order_countsandlog_counts) instead of last indices (last_oidxandlast_lidx) in simulation methods with order functions - Added
inplaceargument for BaseAccessor.set and BaseAccessor.set_between - Fixed
ndimin Data.get_symbol_wrapper - Renamed
ExecuteOrderStateto AccountState andProcessOrderStateto ExecState - Rotational indexing is disabled by default and can be enabled globally using settings
- Order approximation function takes an instance of
ExecStateinstead of state variables - Created classes RandomOHLCData and GBMOHLCData for generation of random OHLC data
- Made numeric tests more precise by reducing tolerance values
- Fixed documentation where argument
intervalwas used instead oftimeframe - Wrote documentation on Portfolio simulation
Version 1.2.0 (3 Apr, 2022)¶
- Integrated PyPortfolioOpt: implemented the function pypfopt_optimize and an infrastructure around it to run arbitrary optimization models from PyPortfolioOpt with a single function call.
- Split generation and reduction of resampling metadata. The generation part now resides in base.resampling.nb, while the reduction part takes place in generic.nb.apply_reduce.
- Implemented wrapper methods for generation of index points (ArrayWrapper.get_index_points) and index ranges (ArrayWrapper.get_index_ranges) from human-readable queries. This helps tremendously in rebalancing.
- Implemented a PortfolioOptimizer class, which is capable of portfolio optimization at regular and irregular intervals, storing the generated allocation data in a compressed format, and analyzing and plotting it. Supports the following input modes:
- Custom allocation function (PortfolioOptimizer.from_allocate_func)
- Custom optimization function (PortfolioOptimizer.from_optimize_func)
- Custom allocations (PortfolioOptimizer.from_allocations)
- Custom filled allocations (PortfolioOptimizer.from_filled_allocations)
- Random allocation (PortfolioOptimizer.from_random)
- Uniform allocation (PortfolioOptimizer.from_uniform)
- PyPortfolioOpt (PortfolioOptimizer.from_pypfopt)
- Universal Portfolios (PortfolioOptimizer.from_universal_algo)
- Added time frames as a parameter to TA-Lib indicators. This will downsample the input data (such as the close price), run the indicator, and upsample it back to the original time frame. Multiple time frame combinations are supported out of the box.
- Implemented convenience methods BaseAccessor.set and BaseAccessor.set_between for setting data based on index points and ranges respectively
- Added an attribute class ExceptLevel that can be used to specify the level by which not to group in
group_by. This is handy when there are many levels and there is a need to group by all levels except assets, for example. - Wrote Portfolio optimization
Version 1.1.2 (12 Mar, 2022)¶
- Added option
skipnato run a TA-Lib indicator on non-NA values only (TA-Lib hates NaN) - Implemented a range of (NB and SP) resampling functions for
- Getting the latest information at each timestamp, supporting bar data (GenericAccessor.realign)
- Resampling to a custom index, both as a regular and meta method (GenericAccessor.resample_to_index)
- Resampling between custom bounds, both as a regular and meta method (GenericAccessor.resample_between_bounds)
- Implemented a Resampler class, which acts as a mapper between the source and target index for best flexibility. It can parse a resampler from Pandas. Also, implemented a range of helper functions for
- Generating a datetime index from frequency (NB)
- Getting the right bound of a datetime index
- Mapping one datetime index to another (NB, Resampler.map_to_target_index)
- Getting datetime index difference (NB, Resampler.index_difference)
- Implemented an interface for resampling complex vectorbt objects in form of an abstract method Wrapping.resample. Also, defined resampling logic for all classes whose Pandas objects can be resampled:
- Data
- OHLCVDFAccessor
- ReturnsAccessor
- Portfolio
- Records and all its subclasses
- Introduced the feature config Data.feature_config, which can be used to define resampling function for each custom column in Data. OHLCV data is resampled automatically.
- Completely refactored handling of in-outputs in Portfolio. Introduced the in-output config Portfolio.in_output_config, which can be used to define the layout, array type, and resampling function for each custom in-output. Appending suffixes (such as
_pcg) to in-output names is now optional. The suffix_pcgshas been renamed to_cs. The resolution mechanism for in-outputs has been distributed over multiple class methods and made more transparent. - The in-output name for returns has been changed from
returns_pcgsto justreturns - Added argument
init_priceto specify the original entry price ofinit_position. This makes calculation of P&L and other metrics more precise and flexible. - Fixed the issue where only the first row in
cash_depositswas applied in Portfolio.from_orders and Portfolio.from_signals - Distributed generic Numba-compiled functions across multiple files
- Enabled passing additional keyword arguments to
get_klinesin BinanceData - Wrote MTF analysis
Version 1.1.1 (25 Feb, 2022)¶
- Data now removes duplicates in index while keeping only the last entry
- Added option
concatto Data.update for being able to disable concatenation of new data with existing data and to only return new data - Added support for chunking in CSVData and HDFData using
chunk_func - Implemented class DataSaver that can periodically collect and save data to disk, and two its subclasses: CSVDataSaver for writing to CSV files and HDFDataSaver for writing to HDF files. This way, one can gradually collect and persist any data from any data provider!
- Fixed unpickling of Config
- Fixed scheduling in DataUpdater such that repeatedly stopping and starting the same updater won't trigger the same job more than once
- QSAdapter will now remove timezone info automatically to prevent issues in QuantStats
- Implemented three new data classes:
- PolygonData for Polygon.io. Can load data of any size in bunches and respects the API rate limits.
- AVData for Alpha Vantage. Does not use the
alpha_vantagelibrary, which isn't actively developed. Instead, it implements a parser of the Alpha Vantage's documentation website and handles communication with the API using the parsed metadata. This enables instant reaction to any changes in the Alpha Vantage's API. The user can still disable the parsing and specify every bit of information manually. - NDLData for Nasdaq Data Link. Supports (time-series) datasets.
- Fixed the condition for a backward fill in fbfill_nb
- Fixed passing
execute_kwargsin IndicatorFactory.with_apply_func. Also, wheneverapply_funcis Numba compiled, makes the parameter selection function Numba compiled as well (jit_select_params=True) and also releases the GIL (nogil=True), so the indicator can be used in multithreading right away.
Version 1.1.0 (20 Feb, 2022)¶
- Removed support for Python 3.6. Wanted to add support for Python 3.10 but stumbled upon issues that can be followed in numba/numba#7812 and numba/numba#7839.
- Removed Bottleneck from optional requirements as it causes installation issues, but it can still be installed manually
- Formatted the entire codebase with Black
- One or more symbols can be selected from a Data instance
- Refactored Data.fetch_kwargs into a symbol dictionary. Getting the keyword arguments used for fetching a specific symbol is now as simple as
fetch_kwargs[symbol]. - Implemented a method Data.merge for merging multiple Data instances
- One or more symbols can be renamed in a Data instance
- Improved aggregation of metrics in StatsBuilderMixin
- Removed
ohlcaccessor to avoid confusion. The only accessor is nowohlcv. - Data.plot automatically plots the data as a candlestick chart if it can find the right price columns, otherwise, it plots each column as a separate line (as it was previously). Also, one can now select a symbol to plot using the
symbolargument. - One metric/subplot can be expanded into multiple metrics/subplots using templates. This enables displaying a variable number of metrics/subplots.
- Data.plots now plots one subplot per symbol
- Delimiter is recognized automatically when dealing with CSV and TSV files
- Implemented a function for pretty-printing directory trees - tree
- Refactored the path matching mechanism for CSV and HDF files. In particular:
- Path unfolding has been renamed to path matching
- Wildcards (
*) are now supported for groups and keys in HDF files - Paths can be further filtered using a regex pattern
match_regex - Functions for path matching have become class methods for seamless inheritance
- The argument
parse_pathsin FileData.pull has been renamed tomatch_paths - The argument
pathin FileData.pull has been renamed topaths
- Symbols that return
Noneor an empty array are skipped. Whenraise_on_erroris True, any symbol raising an error is skipped as well. - Similar to the Python's
helpcommand, vectorbt now has a function phelp that pretty-prints the arguments and docstring of any function. It's main advantage is the ability to skip annotations, which sometimes reduce readability when exploring more complex vectorbt functions usinghelp. - Settings have been refactored once again: it's now clearly visible which key can be accessed via the dot notation (hint: it must be of type ChildDict). Also, the argument
convert_dicts_in Config has been renamed toconvert_children_. - Moved default values of various Data classes from the data.custom module to settings.data to be able to set them globally
- Minor fixes and enhancements across the project
- Wrote documentation on Data
Version 1.0.10 (11 Feb, 2022)¶
- Moved the
per_columnlogic from IndicatorBase.run_pipeline to the indicator function (custom_func). Previously, the indicator function received only one column and parameter combination at a time, which created issues for caching. Now, the pipeline passes all columns and parameter combinations, so it's the responsibility of the indicator function to distribute the combinations properly (no worries,apply_funcwill handle it automatically). - Apply functions (
apply_func) can run on one-dimensional input data just as well as on two-dimensional input data by passingtakes_1d=Trueto IndicatorFactory.with_apply_func. This mode splits each input array (both Pandas and NumPy) into columns and builds a product of columns and parameter combinations. Benchmarks show that this has no real implications on performance + functions that process one column at a time are much easier to write. @taliband@talib_1dannotations were merged into a single@talibannotation that can handle both one and two-dimensional input data- Removed automatic module search when parsing indicator expressions, which degraded performance. It's now recommended to use multi-line expressions and
importstatements. - Renamed
kwargs_to_argstokwargs_as_argsin IndicatorFactory.with_apply_func - Refactored the execute function to enable chunking in indicators
- Fixed the calculation of crossovers. Previously, it ignored a crossover if there was another crossover one tick behind.
- Greatly optimized stacking of output arrays with one column after running an indicator
- Refactored the
as_attrs_behavior in Config. Keys won't be attached to the config instance anymore but managed dynamically (= less side effects when pickling and unpickling). - Implemented a wide range of inputs states, output states, and accumulators for the use in streaming functions, such as in rolling_mean_1d_nb
- Made flexible indexing with flex_select_auto_nb rotational. For example, if there is a smaller array with 3 columns and a bigger one with 6 columns, there is no need to tile the smaller array 2 times to match the bigger one - we can simply rotate over the smaller array.
- Added support for short names in indicator expressions
- Returns can be pre-computed in both Portfolio.from_orders and Portfolio.from_signals by passing the
fill_returns=Trueflag - Fixed save_animation, which previously produced one less iteration
- Wrote SuperFast SuperTrend
Version 1.0.9 (2 Feb, 2022)¶
- Upgraded the parser of indicator expressions:
- Can evaluate the expression using pandas.eval
- Special variables and commands are annotated with the prefix
@ - Supports single as well as multi-line expressions
- Context variables with the same name aren't needlessly re-computed anymore
- Can parse the class name at the beginning of the expression
- Supports one and two-dimensional TA-Lib indicators out-of-the-box
- Supports magnet names for inputs, in-outputs, and parameters
- Can parse settings from within the expression and pass them to IndicatorFactory.from_expr
- Can automatically resolve annotated indicators
- Enabled plotting of any TA-Lib indicator programmatically by parsing its output flags
- Implemented Numba-compiled functions for Wilder's EMA and STD (SP)
- Renamed
from_custom_functowith_custom_funcandfrom_apply_functowith_apply_funcsince those are instance methods - Set
minp(minimum periods) toNonein generic rolling functions to make the values of incomplete windows NaN - Made parameter selection optional in IndicatorFactory.with_apply_func. Setting
select_paramsto False will prepend the iteration index to the arguments of the apply function. - Refactored the
keep_pd=Trueflag to avoid back-and-forth conversion between broadcasted Pandas objects and NumPy arrays. Pandas objects are now directly forwarded to the custom function without any pre-processing. - Renamed
custom_output_propstolazy_outputs - Renamed
select_oneandselect_one_from_objtoselect_colandselect_col_from_objrespectively in Wrapping - Input arrays passed to TA-Lib indicators are converted to the data type
np.double - Renamed
mappingtocontextwhen it comes to templates - Updated plotting methods in indicators.custom
- Data.get also accepts symbol(s)
- Greatly optimized Data.concat
- Wrote documentation on Indicators
Version 1.0.8 (25 Jan, 2022)¶
- Implemented the following Numba-compiled functions:
- Ranking and rolling ranking (SP)
- Covariance and rolling covariance (SP)
- Rolling sum and product (SP)
- Rolling weighted average (SP)
- Rolling argmin and argmax
- Demeaning within a group
- Implemented volume-weighted average price (VWAP)
- Built a powerful engine for parsing indicator expressions. Using IndicatorFactory.from_expr, an indicator can be automatically constructed out of an expression string, such as
"rolling_mean((low + high) / 2, 10)"! IndicatorFactory can recognize common inputs such aslowand the number of outputs. For parameters and more cryptic inputs, the user can provide a prefix:"rolling_mean(abs(in_ts), p_window)". Moreover, apart from preset functions such asrolling_mean, whenever it recognizes an unknown function, searches for its implementation in various parts of vectorbt and NumPy. Supports NumExpr to accelerate simpler expressions. - Translated each one of WorldQuant's 101 Formulaic Alphas into an indicator expression and implemented a convenience method IndicatorFactory.from_wqa101 (also as a shortcut
vbt.wqa101) for executing them - Unified column grouping for matrices and records across the entire codebase. Most logic now resides in the sub-package base.grouping. Also, most functions (apart from the portfolio-related ones) do not require strict group ordering anymore.
- Added chunking specification for labeling functions
- Fixed Config.prettify for non-string keys
- Wrote Basic RSI strategy
Version 1.0.7 (16 Jan, 2022)¶
- Changed
np.int_tonp.integerwhen passed tonp.issubdtype - Refactored auto-aligned initial cash to be based on free cash flows and cash deposits
- Upgraded the string parser of deep_getattr to accept strings of chained method calls (more intuitive)
- Implemented superfast Pearson correlation coefficient and its rolling version
- Created the class Analyzable, which combines Wrapping and builder mixins
- Metrics and subplots that require a single column won't raise an error if the object is two-dimensional and has only one column
- Grouper can return a group map, which isn't tied to a strict group ordering and is easier to use outside of Numba
- Wrote documentation on Building blocks
Version 1.0.6 (9 Jan, 2022)¶
- Benchmark can be disabled by passing
bm_close=Falseto Portfolio - Wrote documentation on Fundamentals
Version 1.0.5 (8 Jan, 2022)¶
- Fixed Portfolio.from_signals for
direction='both'andsize_type='value'. Previously, the position couldn't be properly reversed. - Avoid sorting paths in FileData if they are passed as a sequence
Version 1.0.4 (6 Jan, 2022)¶
- Set benchmark easily and also globally (#32) by passing
bm_closeto Portfolio. Works similarly to Portfolio.close. - Shortened registry names (such as from
ca_registrytoca_reg)
Version 1.0.3 (5 Jan, 2022)¶
- Automatic discovery of symbols for local data (#27): No more need to specify a path to each CSV/HDF file or HDF key. Passing a path to a directory will traverse each file in this directory. Passing a glob-style pattern will use
glob.globto traverse all files that match this pattern. Passing an HDF file will extract all keys inside this file. All the options above can be combined in arbitrary ways. - Minor fixes in the formatting module
- Removed strict ordering of group and shape suffixes in Portfolio.get_in_output and Portfolio.in_outputs_indexing_func. For instance, there is no more difference between in-outputs with names
myinout_2d_pcandmyinout_pc_2d. - Improved readability of cacheable setups: When displaying the status overview, objects are represented by shorter, human-readable strings, and also contain the position of this object in all the objects registered globally and sorted by time. For instance,
portfolio:2means that there exist 2 more Portfolio objects created earlier than this object. This makes it easier to manage memory and to debug garbage collection. - Wrapping in-outputs automatically: Implements the method Portfolio.get_in_output, which can be used to access and automatically wrap any in-output object from Portfolio.in_outputs.
- All registries can be accessed directly via
vbt - Updates and minor fixes to the ca_registry and ch_registry modules
- Disabled parallelization of generate_both, which behaved unexpectedly
- Fixed
in_outputsin Portfolio.from_order_func to work with Numba 0.53.1. This requires the user to definein_outputsas a named tuple prior to passing to the method. - Added mapping of
windowtorolling_periodin the QuantStats adapter