Latest release notes¶
All notable changes in reverse chronological order.
Version 2024.8.20 ¶
- Portfolio instances now accept the argument
weights, which is a vector of weights, one per column. Weights are applied to the initial position, initial cash, cash deposits, cash earnings, as well as order records. They are used to scale up or down a column relative to its group or the entire portfolio. Weights can be applied after creating a portfolio instance with Portfolio.apply_weights and optionally rescaled by group by passingrescale=Trueto the same method. - Implemented the data class FinPyData for
findatapy(https://github.com/cuemacro/findatapy), which allows pulling data from Bloomberg, Eikon, Quandl, Dukascopy, etc. - Implemented portfolio views (that is, methods and properties that return other portfolio instances) that include orders of either long positions (Portfolio.long_view) or short positions (Portfolio.short_view)
- Implemented methods to convert Pandas Series and DataFrames to Data instances: OHLC(V) DataFrames can be converted via
data = df.vbt.ohlcv.to_data()while Series/DataFrames where symbols are columns can be converted via a more generaldata = df.vbt.to_data() - Indicators now behave like regular arrays when combined with other arrays. Also, when an indicator has multiple outputs but there's an output of the same name as the short name of the indicator (like "atr" in ATR), that one output becomes the main output that gets combined.
- Added options
PriceType.NextValidOpen(or "nextvalidopen") andPriceType.NextValidClose(or "nextvalidclose") that use the next non-NA open and close price respectively - Fixed TVClient.search_symbol. Added a back-adjustment option for symbols ending with "!A". Also, the user agent is now a global constant (see
vbt.data.custom.tv.USER_AGENT) and is used in most connection settings by default. - Data.add_symbol re-uses keyword arguments previously used in fetching (if
reuse_fetch_kwargsis True, which is now default). Also, Data.add_feature can use pulling instead of running as well (ifpull_featureis True). - Fixed plotting of ADX
- Fixed package version comparison that leads to "NameError: name 'post1' is not defined"
- Fixed
read_onlyargument resolution in DuckDBData - Allowed renaming index in Data
- As per @rayanbenredjeb suggestion and contribution (thank you!), reduced two loops computation to a single loop in covariance and correlation functions
- Fixed parameter index for
per_column=Truein IndicatorFactory - Fixed mapping of start and end dates in BentoData
- Adapted scheduling functionality to the
schedulepackage of the version 1.2.2 and above - Fixed integer size granularity leading to an incorrect order size due to floating-point errors
- Fixed NaN resolution in PIVOTINFO
- Re-added the arguments
use_asset_returnsandbm_returnsto portfolio plotting methods
Version 2024.6.19¶
- PortfolioOptimizer.from_allocate_func and PortfolioOptimizer.from_optimize_func accept an argument
group_execute_kwargsthat controls the execution of groups - PortfolioOptimizer.from_optimize_func accepts Takeable instances. Taking is done with Splitter.take_range_from_takeable, which also accepts many formats including arrays with a different index.
- Most objects now have a
split_applymethod that splits the object and applies a function on each chunk. The first argument is the function while other arguments are distributed in the same way as in the methodsplit. - If the index of data pulled by Data is not sorted, it will be sorted while keeping the order of duplicates. If it's monotonically decreasing, it will be reversed.
- SQLData sorts data by index directly in the database
- In-house Plotly figures have got a method
select_rangethat recursively selects a specified date range across all traces and shapes in the figure, making it especially useful for rendering granular data quickly or for exploring specific parts of data more efficiently. By default, it returns a new figure. - Fixed NaN resolution in PIVOTINFO
- Argument
tzpassed by the user when pulling data with most Data subclasses will also default totz_localize(not only totz_convert) - Added
eval_idto all chunking classes. This enables nested chunking since now the user can specify which function (or decorator) should evaluate which array, for example, to define different execution rules for different arrays. If theeval_idof the function doesn't match with theeval_idof the array, the array will be forwarded downstream to be evaluated by the inner function. - Added the class Task, which behaves the same as the tuple format
(func, args, kwargs), but in a more user-friendly way. Argumentfuncs_argsin Executor.run and other places has been renamed totasks. Also, renamed the optiondistribute="calls"todistribute="tasks". - Executor can merge execution results by accepting
merge_funcandmerge_kwargs. Also, it can filter outNoResultinstances iffilter_resultsis True (not default) and raise an error if all results areNoResultinstances andraise_no_resultsis True (default). Generally, the logic to filter out missing results has been standardized and outsourced to filter_out_no_results. - Implemented a new decorator
@iteratedthat takes a function and executes it repeatedly on values of an argument passed to this function (usually the first argument, but can be specified withover_arg) - Connections in DuckDBData are closed automatically when provided as a string. This allows simultaneously opening two connections with different access modes.
- Cache clearing (
chunk_clear_cache), garbage collection (chunk_collect_garbage), and delay (chunk_delay) can be done after executing each (super-)chunk with Executor - Progress bars are now hidden within parallel workflows. Also, tqdm bars are no longer opened by default when progress shouldn't be shown (can be changed by setting
force_open_bar=True) - Signal factory accepts
jittedargument to control jitting of generation functions - Integrated Smart Money Concepts (SMC) into IndicatorFactory.from_smc
- Added 5 different Numba-compiled implementations of (rolling) Hurst exponent in HURST
Version 2024.5.15¶
- Refactored execution engines. In addition to the function execute, there's now a class Executor that takes execution-related arguments and exposes a method Executor.run to run these arguments on function(s) calls. Whenever the function execute is called, it constructs an instance of the executor and calls the run method. Also, outsourced many preprocessing and postprocessing workflows to standalone methods that can be overridden by the user, such as Executor.call_pre_chunk_func that is called before a chunk is processed. In addition, keys can be supplied along with function calls. Each key is a description of what the function call represents, and can be used in progress bars.
- Implemented (super-)chunk caching in the executor. If (super-)chunking is enabled with
cache_chunks=Trueand execution-specific caching directory is specified inchunk_cache_dir(will be created if not existing), the results of each chunk will be serialized and stored on disk. Whenever the execution is stopped and then re-run, the results of each (previously cached) chunk will be loaded from disk. Ifpre_clear_chunk_cacheis True, will clear the caching directory before execution. Ifrelease_chunk_cacheis True, won't keep the results in memory but replace them with a dummy object. Then, when the entire execution is complete, will replace all dummy objects with actual results loaded from disk. By default (post_clear_chunk_cache=True), will remove the caching directory once the entire execution is complete. - Resolution of defaults in all execution engines, the executor, the chunker, and the parameterizer now happens at the initialization time for atomicity
- Each progress bar can now display a relevant description of the currently processed item. For instance, a daily range between the dates "2024-01-01 00:00:00" and "2025-01-01 00:00:00" is displayed as "2024-01-01 → 2025-01-01". Progress description is shown as a postfix to avoid progress bars of varying lengths. This option (
as_postfix) can be changed in the pbar-related settings. - Progress bars are now enabled on default (i.e., there's no need to provide
show_progress=Trueanymore), but will be displayed only if they aren't complete before a number of seconds (delay) - Implemented a context manager for progress bars ProgressBar that replaces the function
get_pbar. It wraps atqdminstance and supercharges it with userful enhancements while exposing identically-named methods. For example, ProgressBar.update not only updates thetqdminstance but also calls some pre-update and post-update workflows. - Enabled reusable and nested progress bars by implementing a registry class PBarRegistry and its instance pbar_reg, that registers all currently active and pending, parent and child progress bars. Each progress bar gets its own unique identifier, which can be either supplied by the user or generated automatically. Whenever a child progress bar finishes iterating, it gets a pending status; later, when a progress bar with the same identifier should be registered, it reuses the already registered pending progress bar. Once the parent progress bar stops, all children are closed and deregistered. The parent-child relationship is determined based on the time each bar was opened/updated/closed. To disable, set
reuseto False. - All progress bars can be shown or hidden within a code block by using the context managers ProgressShown and ProgressHidden respectively
- The case of the day unit has been changed to uppercase (from "d" to "D")
- Extended offset string translation. For example, "businessmonthstart" will be translated to "BMS". Also, all aliases now work the same way in both older and newer Pandas versions.
- Created many convenient datetime shortcuts, for example
vbt.timestamp()returns the same aspd.Timestamp.now()whilevbt.offset("M")returnspd.offsets.MonthBegin() - Simulation range can now be modified from within a simulation. Each context has new fields SimulationContext.sim_start and SimulationContext.sim_end, which are guaranteed to be one-dimensional NumPy arrays with values per group. Lowering the second array in-place will have an effect on the current simulation. In particular, setting it to the next row or earlier will process the current row to the end and stop the simulation at the next one; this can be done conveniently by calling
vbt.stop_group_sim_nb(c). - Simulation range passed to a simulation method is persisted in the simulation output (SimulationOutput) per column (as opposed to the per-group layout when being passed to the method)
- Adapted portfolio analysis as well as return methods and properties to simulation ranges. Whenever a simulation range is active, the respective Numba function will process data only within this range. Moreover, any simulation range can be activated/modified/deactivated dynamically, even in stats. For example,
pf.get_sharpe_ratio(sim_start="2024")will return the Sharpe ratio only for the rows from 2024 onwards. Ifrec_sim_rangeis False (default), only the latest analysis step respects the simulation range. In the example above, returns are computed on all rows while only the Sharpe ratio is computed within the range. Ifrec_sim_rangeis True, the entire analysis chain respects the simulation range (similar to backpropagation). Here,pf.get_sharpe_ratio(sim_start="2024", rec_sim_range=True)will return the Sharpe ratio as if orders before 2024 didn't exist. - Renamed metrics "Start", "End", and "Period" to "Start Index", "End Index", and "Total Duration" respectively. These metrics respect the currently active simulation range.
- Improved most portfolio subplots. They respect the currently active simulation range and, similarly to metrics, can be called as class methods on already pre-calculated arrays.
- Redesigned Numba-compiled return metrics. Rolling metrics have become standalone Numba functions.
- Symbol sorting in
list_symbolsof custom data classes is now optional. If sorting has been disabled by the user, symbols will be returned in the native order of the data provider. - Stops won't be executed right away if the option
StopExitPrice.Closeis active - A human-readable error will be thrown if the user failed to provide arguments as a tuple
- OHLC DataFrames can be passed as
closein portfolio factory methods. They will be recognized as data-like instances if all features ("Open", "High", "Low", and "Close") are present. - Refactored Numba functions in portfolio.nb.ctx_helpers. Those functions that have a prefix "col" or "group" can now be called from any callback, not only from callbacks that have a compatible context.
- Whenever TVData fails at pulling a symbol, it retries several times
Version 2024.4.1¶
- Limit and stop price checks are more robust to floating-point errors
- Fixed partial resolution of keyword arguments when merging VBT objects
- Fixed
size_typenot being applied tomin_sizeandmax_sizein Portfolio.from_signals - BaseAccessor.combine always produces a DataFrame when passing a sequence of arrays (even with one array)
- Providing a list with a single parameter value to an indicator always produces a DataFrame
- Created decorators for all profilers in profiling
- All simulation methods now take arguments
sim_startandsim_end(both defaulting to None) that indicate at which row the simulation should start and end for each column or group. This will skip all rows precedingsim_startand succeedingsim_end, which may result in a faster execution, especially for simulations with sparse orders (such as due to signal unraveling). Both arguments can be provided as datetimes and human-readable strings - they will be converted to indices automatically. Also, many simulation methods acceptsim_start="auto"andsim_end="auto"to determine an optimal simulation range from inputs such as signals or order size. - If an indicator has a single output (especially with a generic name such as "real"), VBT creates two dynamic aliases for it: the short name of the indicator (such as "sma") and "output". For example, the method
real_crossed_abovecan be also accessed viasma_crossed_above,output_crossed_above, and even justcrossed_above(without any prefix). - Renamed the field
sub_idin templates toeval_id - Added
eval_idto both parameters (Param) and takeables (Takeable). This enables nested parameterization and splitting since now the user can specify which function (or decorator) should evaluate which parameter, for example, to define different execution rules for different parameters. If theeval_idof the function doesn't match with theeval_idof the parameter, the parameter will be forwarded downstream to be evaluated by the inner function. - Standardized attribute classes, such as Param. To define an attribute class, decorate it with
@define, subclass define.mixin, and define fields with define.field. Also, added a concept of a missing value (MISSING), which powers required and optional fields that don't raise an error during the initialization step, only at the validation step. This enables one key feature: instances of attribute classes know which arguments were explicitly provided by the user for better printing and more granular merging of multiple instances. - Fixed potential division-by-zero errors in portfolio records
- Patched frequency-based
dt_stop - When translating a datetime object to nanoseconds, there's now a global flag
tz_naive_nsin settings.datetime_ that controls whether the timezone should be dropped (True) or converted to UTC (False) before conversion - Extended portfolio helper functions in portfolio.nb.ctx_helpers. For instance, the user can now get most information for a custom column or group.
- Patched
length="optimize"in Splitter.from_n_rolling - Renamed
index_stack_kwargstoclean_index_kwargs - Most classes now subclass HasItems and Paramable. When calling
obj.items(), it splits the object along the column/group axis and returns an iterator of column/group labels and sub-objects where each sub-object contains only one column/group of data. Also, when callingobj.as_param()orvbt.Param(obj), it returns a Param instance where values are sub-objects and keys are column/group labels. This way, the user can use objects of any complexity as parameters to process only one configuration at a time. - Renamed
yield_group_lens_idxstoiter_group_lens,yield_group_map_idxstoiter_group_map, and__iter__toiter_groupsin Grouper - Records.records_readable and MappedArray.mapped_readable have now an alias
readable - Most classes now subclass IndexApplier with methods for working with index and columns. For example, to drop a parameter from a portfolio:
new_pf = pf.drop_levels(param_name) - Parameter conditions (Param.condition) can be provided as a template. Also, to access any key (or level in the parameter index) of a parameter combination, wrap the parameter (or level) name with
__. For example, when combining a fast and slow SMA indicators, the condition can be"__fast_window__ < __slow_window__"iffast_windowandslow_windoware level names in the parameter index. - Short name and level names of an indicator can be changed using IndicatorBase.rename and IndicatorBase.rename_levels respectively
- Method
splitof most objects, as well as the decorators@splitand@cv_split, allow providing keyword arguments related to splitting, taking, and applying as variable arguments (in addition tosplitter_kwargs,take_kwargs, andapply_kwargs). The distribution of these arguments over the the respective functions is done automatically. Also, the splitting method can be guessed by keyword arguments whensplitteris None. For example, callingobj.split(n=10, into="stacked")will call Splitter.from_n_rolling withn=10and then Splitter.take withinto="stacked" - Adapted the package https://github.com/sam31415/timeseriescv in generic.splitting.purged and added factory methods Splitter.from_purged_walkforward and Splitter.from_purged_kfold
- Renamed
SKLSplittertoSplitterCV - Similar to StopExitPrice for stop orders, added LimitOrderPrice for limit orders
- Wrote Backtest powerful intraday trading strategies
Version 2024.2.22¶
- Doing the star-import
from vectorbtpro import *will return a minimal list of imports that are essential to working with VBT, such aspd,np, andvbtitself. This will not pollute the namespace with VBT-own objects as they are exclusively accessible fromvbt. In case of any static analysis issues, VBT can still be imported in a classic way -import vectorbtpro as vbt. The start import behavior can be controlled by the settingstar_importin settings.importing, which accepts be "all", "vbt" (previous behavior), "minimal" (current behavior), and "none". This setting can be changed only via a configuration file. All notebooks and website examples have been updated accordingly. - Implemented portfolio methods (and their corresponding properties) for calculating the average entry price and exit price of each position and bar - Portfolio.get_position_entry_price and Portfolio.get_position_exit_price respectively
- Modeling of signal pairs for SignalsAccessor.between_ranges and other methods has been redesigned and is now based on
relationof type SignalRelation. For example, behavior offrom_other=Truecan now be replicated withrelation="manyone". Also, changedothertotargetacross SignalsAccessor. - Implemented the following methods for signal unraveling:
- SignalsAccessor.unravel: "unravels" each signal to a separate column
- SignalsAccessor.unravel_between: "unravels" each signal pair in one or two masks to a separate column
- SignalsAccessor.ravel: "ravels" all separate columns back into one column
- Standardized datetime and frequency functionality across the entire codebase. Added new frequency aliases, such as week days and months; for example,
every="monday"will return an index with only mondays. Frequency is now allowed to be a date offset of any complexity, and will be stored in its original format. Only when actually needed, it can be converted into a timedelta by approximation. Also, frequency can now being detected automatically from index when set to"auto"(this is the new global default, see infer_index_freq for other options). Same for year frequency (the default remains "365 days" for backward compatibility, see ReturnsAccessor.get_year_freq for other options). - Records.to_readable and MappedArray.to_readable accept
expand_columns=Trueto split column tuples into multiple columns - one per level - Fixed row stacking for one-dimensional NumPy arrays
- Fixed handling of colons in symbols such as
"BTC/USDT:USDT"in CCXTData. Previously, the first part was mistaken for an exchange even if an exchange was provided. - Added option
if_existsto IndicatorFactory.register_custom_indicator - Added option
magnet_kwargsto Data.run - Added Python 3.12 support
Version 2024.1.30¶
- Introduced a new option
cash_deposits_as_inputthat controls whether cash deposits should be added to the input value rather than subtracted from the output value when computing a return - Implemented the methods IndicatorBase.dropna and Data.dropna to drop any missing values from an indicator and a data instance respectively
- Implemented or extended the 4 most basic operations on data. Each operation comprises 5 different methods: one for columns, one for keys, one for features, one for symbols, and one that can determine the right method automatically (listed below). Also, features and symbols have become case-insensitive.
- Data.select: select one or more features or symbols
- Data.add: add (exactly) one feature or symbol
- Data.rename: rename one or more features or symbols
- Data.remove: remove one or more features or symbols
- Expanded registration of custom indicators. A custom indicator now can be registered under a custom location (which defaults to
"custom"). Custom locations are effectively indicator groups or tags, and are stored as keys in IndicatorFactory.custom_indicators; they can be listed with IndicatorFactory.list_custom_locations. Built-in indicators can be added to custom locations too. - Data.run can return a data instance
- Fixed path resolution and handling of keys with a period (
.) in HDFData - Fixed filtering by the arguments
startandendin DuckDBData - Improved resolution of datetime-like arguments (specifically
dt_stop) in BasePreparer.prepare_dt_obj. When providing a date such as"2024-01-01"or a time such as"16:00", the stop is marked at the provided datetime. When providing a frequency such as"daily", the stop is marked at the end of the last bar of the current period. This behavior can be changed by overridinglast_beforein the argument config of the particular argument. Also, when providing just a time, the marked datetime will overflow to the next day if the requested time comes before the current time. In addition, the user can dynamically pass changes to the argument config by passingarg_configas a regular argument, which will be merged over the actual argument config. - Implemented NB function init_FSInOutputs_nb to initialize in-outputs
- Implemented a function get_api_ref that for any VBT object returns the corresponding link to the private website and source code. Another function open_api_ref does the same but then automatically opens the link in a browser. If a third-party object was provided, parses the path to the object and opens the first search result on DuckDuckGo.
- Fixed an error that gets raised when providing an integer (as opposed to floating) account state field to
long_buy_nb,long_sell_nb,short_sell_nb, orshort_buy_nbin portfolio.nb.core - Most classes now have a method Chainable.pipe that enables built-in and user-defined methods in method chains. Supports deep attribute retrieval.
- Added a light and dark color palette toggle to the website
- Wrote Easily cross-validate parameters to boost your trading strategy