Skip to content

nb module

Numba-compiled functions.

Provides an arsenal of Numba-compiled functions that are used for portfolio modeling, such as generating and filling orders. These only accept NumPy arrays and other Numba-compatible types.

Note

vectorbt treats matrices as first-class citizens and expects input arrays to be 2-dim, unless function has suffix _1d or is meant to be input to another function.

All functions passed as argument should be Numba-compiled.

Records should retain the order they were created in.

Warning

Accumulation of roundoff error possible. See here for explanation.

Rounding errors can cause trades and positions to not close properly:

>>> print('%.50f' % 0.1)  # has positive error
0.10000000000000000555111512312578270211815834045410

>>> # many buy transactions with positive error -> cannot close position
>>> sum([0.1 for _ in range(1000000)]) - 100000
1.3328826753422618e-06

>>> print('%.50f' % 0.3)  # has negative error
0.29999999999999998889776975374843459576368331909180

>>> # many sell transactions with negative error -> cannot close position
>>> 300000 - sum([0.3 for _ in range(1000000)])
5.657668225467205e-06

While vectorbt has implemented tolerance checks when comparing floats for equality, adding/subtracting small amounts large number of times may still introduce a noticable error that cannot be corrected post factum.

To mitigate this issue, avoid repeating lots of micro-transactions of the same sign. For example, reduce by np.inf or position_now to close a long/short position.

See vectorbt.utils.math_ for current tolerance values.


approx_order_value_nb function

approx_order_value_nb(
    size,
    size_type,
    direction,
    cash_now,
    position_now,
    free_cash_now,
    val_price_now,
    value_now
)

Approximate value of an order.


asset_flow_nb function

asset_flow_nb(
    target_shape,
    order_records,
    col_map,
    direction
)

Get asset flow series per column.

Returns the total transacted amount of assets at each time step.


asset_returns_nb function

asset_returns_nb(
    cash_flow,
    asset_value
)

Get asset return series per column/group.


asset_value_grouped_nb function

asset_value_grouped_nb(
    asset_value,
    group_lens
)

Get asset value series per group.


asset_value_nb function

asset_value_nb(
    close,
    assets
)

Get asset value series per column.


assets_nb function

assets_nb(
    asset_flow
)

Get asset series per column.

Returns the current position at each time step.


benchmark_value_grouped_nb function

benchmark_value_grouped_nb(
    close,
    group_lens,
    init_cash_grouped
)

Get market value per group.


benchmark_value_nb function

benchmark_value_nb(
    close,
    init_cash
)

Get market value per column.


build_call_seq function

build_call_seq(
    target_shape,
    group_lens,
    call_seq_type=0
)

Not compiled but faster version of build_call_seq_nb().


build_call_seq_nb function

build_call_seq_nb(
    target_shape,
    group_lens,
    call_seq_type=0
)

Build a new call sequence array.


buy_nb function

buy_nb(
    exec_state,
    size,
    price,
    direction=2,
    fees=0.0,
    fixed_fees=0.0,
    slippage=0.0,
    min_size=0.0,
    max_size=inf,
    size_granularity=nan,
    lock_cash=False,
    allow_partial=True,
    percent=nan
)

Buy or/and cover.


cash_flow_grouped_nb function

cash_flow_grouped_nb(
    cash_flow,
    group_lens
)

Get cash flow series per group.


cash_flow_nb function

cash_flow_nb(
    target_shape,
    order_records,
    col_map,
    free
)

Get (free) cash flow series per column.


cash_grouped_nb function

cash_grouped_nb(
    target_shape,
    cash_flow_grouped,
    group_lens,
    init_cash_grouped
)

Get cash series per group.


cash_in_sim_order_nb function

cash_in_sim_order_nb(
    cash_flow,
    group_lens,
    init_cash_grouped,
    call_seq
)

Get cash series in simulation order.


cash_nb function

cash_nb(
    cash_flow,
    init_cash
)

Get cash series per column.


check_group_init_cash_nb function

check_group_init_cash_nb(
    group_lens,
    n_cols,
    init_cash,
    cash_sharing
)

Check init_cash.


check_group_lens_nb function

check_group_lens_nb(
    group_lens,
    n_cols
)

Check group_lens.


close_position_nb function

close_position_nb(
    price=inf,
    fees=0.0,
    fixed_fees=0.0,
    slippage=0.0,
    min_size=0.0,
    max_size=inf,
    size_granularity=nan,
    reject_prob=0.0,
    lock_cash=False,
    allow_partial=True,
    raise_reject=False,
    log=False
)

Close the current position.


copy_trade_record_nb function

copy_trade_record_nb(
    record,
    trade_record
)

Copy a trade record.


dir_enex_signal_func_nb function

dir_enex_signal_func_nb(
    c,
    entries,
    exits,
    direction
)

Resolve direction-aware signals out of entries, exits, and direction.


execute_order_nb function

execute_order_nb(
    state,
    order
)

Execute an order given the current state.

Args

state : ProcessOrderState
See ProcessOrderState.
order : Order
See Order.

Error is thrown if an input has value that is not expected. Order is ignored if its execution has no effect on current balance. Order is rejected if an input goes over a limit/restriction.


fill_entry_trades_in_position_nb function

fill_entry_trades_in_position_nb(
    order_records,
    col_map,
    col,
    first_c,
    last_c,
    first_entry_size,
    first_entry_fees,
    exit_idx,
    exit_size_sum,
    exit_gross_sum,
    exit_fees_sum,
    direction,
    status,
    parent_id,
    trade_records,
    tidx
)

Fill entry trades located within a single position.


fill_log_record_nb function

fill_log_record_nb(
    record,
    record_id,
    i,
    col,
    group,
    cash,
    position,
    debt,
    free_cash,
    val_price,
    value,
    order,
    new_cash,
    new_position,
    new_debt,
    new_free_cash,
    new_val_price,
    new_value,
    order_result,
    order_id
)

Fill a log record.


fill_order_record_nb function

fill_order_record_nb(
    record,
    record_id,
    i,
    col,
    order_result
)

Fill an order record.


fill_position_record_nb function

fill_position_record_nb(
    record,
    id_,
    trade_records
)

Fill a position record by aggregating trade records.


fill_trade_record_nb function

fill_trade_record_nb(
    record,
    id_,
    col,
    size,
    entry_idx,
    entry_price,
    entry_fees,
    exit_idx,
    exit_price,
    exit_fees,
    direction,
    status,
    parent_id
)

Fill a trade record.


final_value_nb function

final_value_nb(
    total_profit,
    init_cash
)

Get total profit per column/group.


flex_simulate_nb function

flex_simulate_nb(
    target_shape,
    group_lens,
    init_cash,
    cash_sharing,
    segment_mask=array(True),
    call_pre_segment=False,
    call_post_segment=False,
    pre_sim_func_nb=no_pre_func_nb,
    pre_sim_args=(),
    post_sim_func_nb=no_post_func_nb,
    post_sim_args=(),
    pre_group_func_nb=no_pre_func_nb,
    pre_group_args=(),
    post_group_func_nb=no_post_func_nb,
    post_group_args=(),
    pre_segment_func_nb=no_pre_func_nb,
    pre_segment_args=(),
    post_segment_func_nb=no_post_func_nb,
    post_segment_args=(),
    flex_order_func_nb=no_flex_order_func_nb,
    flex_order_args=(),
    post_order_func_nb=no_post_func_nb,
    post_order_args=(),
    close=array(nan),
    ffill_val_price=True,
    update_value=False,
    fill_pos_record=True,
    max_orders=None,
    max_logs=0,
    flex_2d=True
)

Same as simulate_nb(), but with no predefined call sequence.

In contrast to order_func_nb insimulate_nb(), post_order_func_nb is a segment-level order function that returns a column along with the order, and gets repeatedly called until some condition is met. This allows multiple orders to be issued within a single element and in an arbitrary order.

The order function should accept FlexOrderContext, unpacked tuple from pre_segment_func_nb, and *flex_order_args. Should return column and Order. To break out of the loop, return column of -1.

Note

Since one element can now accommodate multiple orders, you may run into "order_records index out of range" exception. In this case, you should increase max_orders. This cannot be done automatically and dynamically to avoid performance degradation.

Usage

>>> import numpy as np
>>> from numba import njit
>>> from vectorbt.portfolio.enums import SizeType, Direction
>>> from vectorbt.portfolio.nb import (
...     get_col_elem_nb,
...     order_nb,
...     order_nothing_nb,
...     flex_simulate_nb,
...     flex_simulate_row_wise_nb,
...     sort_call_seq_out_nb
... )

>>> @njit
... def pre_sim_func_nb(c):
...     print('before simulation')
...     return ()

>>> @njit
... def pre_group_func_nb(c):
...     print('\tbefore group', c.group)
...     # Create temporary arrays and pass them down the stack
...     order_value_out = np.empty(c.group_len, dtype=np.float_)
...     call_seq_out = np.empty(c.group_len, dtype=np.int_)
...     # Forward down the stack
...     return (order_value_out, call_seq_out)

>>> @njit
... def pre_segment_func_nb(c, order_value_out, call_seq_out, size, price, size_type, direction):
...     print('\t\tbefore segment', c.i)
...     for col in range(c.from_col, c.to_col):
...         # Here we use order price for group valuation
...         c.last_val_price[col] = get_col_elem_nb(c, col, price)
...
...     # Same as for simulate_nb, but since we don't have a predefined c.call_seq_now anymore,
...     # we need to store our new call sequence somewhere else
...     call_seq_out[:] = np.arange(c.group_len)
...     sort_call_seq_out_nb(c, size, size_type, direction, order_value_out, call_seq_out)
...
...     # Forward the sorted call sequence
...     return (call_seq_out,)

>>> @njit
... def flex_order_func_nb(c, call_seq_out, size, price, size_type, direction, fees, fixed_fees, slippage):
...     if c.call_idx < c.group_len:
...         col = c.from_col + call_seq_out[c.call_idx]
...         print('\t\t\tcreating order', c.call_idx, 'at column', col)
...         # # Create and return an order
...         return col, order_nb(
...             size=get_col_elem_nb(c, col, size),
...             price=get_col_elem_nb(c, col, price),
...             size_type=get_col_elem_nb(c, col, size_type),
...             direction=get_col_elem_nb(c, col, direction),
...             fees=get_col_elem_nb(c, col, fees),
...             fixed_fees=get_col_elem_nb(c, col, fixed_fees),
...             slippage=get_col_elem_nb(c, col, slippage)
...         )
...     # All columns already processed -> break the loop
...     print('\t\t\tbreaking out of the loop')
...     return -1, order_nothing_nb()

>>> @njit
... def post_order_func_nb(c, call_seq_out):
...     print('\t\t\t\torder status:', c.order_result.status)
...     return None

>>> @njit
... def post_segment_func_nb(c, order_value_out, call_seq_out):
...     print('\t\tafter segment', c.i)
...     return None

>>> @njit
... def post_group_func_nb(c):
...     print('\tafter group', c.group)
...     return None

>>> @njit
... def post_sim_func_nb(c):
...     print('after simulation')
...     return None

>>> target_shape = (5, 3)
>>> np.random.seed(42)
>>> group_lens = np.array([3])  # one group of three columns
>>> init_cash = np.array([100.])  # one capital per group
>>> cash_sharing = True
>>> call_seq = build_call_seq(target_shape, group_lens)  # will be overridden
>>> segment_mask = np.array([True, False, True, False, True])[:, None]
>>> segment_mask = np.copy(np.broadcast_to(segment_mask, target_shape))
>>> size = np.asarray(1 / target_shape[1])  # scalars must become 0-dim arrays
>>> price = close = np.random.uniform(1, 10, size=target_shape)
>>> size_type = np.asarray(SizeType.TargetPercent)
>>> direction = np.asarray(Direction.LongOnly)
>>> fees = np.asarray(0.001)
>>> fixed_fees = np.asarray(1.)
>>> slippage = np.asarray(0.001)

>>> order_records, log_records = flex_simulate_nb(
...     target_shape,
...     group_lens,
...     init_cash,
...     cash_sharing,
...     segment_mask=segment_mask,
...     pre_sim_func_nb=pre_sim_func_nb,
...     post_sim_func_nb=post_sim_func_nb,
...     pre_group_func_nb=pre_group_func_nb,
...     post_group_func_nb=post_group_func_nb,
...     pre_segment_func_nb=pre_segment_func_nb,
...     pre_segment_args=(size, price, size_type, direction),
...     post_segment_func_nb=post_segment_func_nb,
...     flex_order_func_nb=flex_order_func_nb,
...     flex_order_args=(size, price, size_type, direction, fees, fixed_fees, slippage),
...     post_order_func_nb=post_order_func_nb
... )
before simulation
    before group 0
        before segment 0
            creating order 0 at column 0
                order status: 0
            creating order 1 at column 1
                order status: 0
            creating order 2 at column 2
                order status: 0
            breaking out of the loop
        after segment 0
        before segment 2
            creating order 0 at column 1
                order status: 0
            creating order 1 at column 2
                order status: 0
            creating order 2 at column 0
                order status: 0
            breaking out of the loop
        after segment 2
        before segment 4
            creating order 0 at column 0
                order status: 0
            creating order 1 at column 2
                order status: 0
            creating order 2 at column 1
                order status: 0
            breaking out of the loop
        after segment 4
    after group 0
after simulation

flex_simulate_row_wise_nb function

flex_simulate_row_wise_nb(
    target_shape,
    group_lens,
    init_cash,
    cash_sharing,
    segment_mask=array(True),
    call_pre_segment=False,
    call_post_segment=False,
    pre_sim_func_nb=no_pre_func_nb,
    pre_sim_args=(),
    post_sim_func_nb=no_post_func_nb,
    post_sim_args=(),
    pre_row_func_nb=no_pre_func_nb,
    pre_row_args=(),
    post_row_func_nb=no_post_func_nb,
    post_row_args=(),
    pre_segment_func_nb=no_pre_func_nb,
    pre_segment_args=(),
    post_segment_func_nb=no_post_func_nb,
    post_segment_args=(),
    flex_order_func_nb=no_flex_order_func_nb,
    flex_order_args=(),
    post_order_func_nb=no_post_func_nb,
    post_order_args=(),
    close=array(nan),
    ffill_val_price=True,
    update_value=False,
    fill_pos_record=True,
    max_orders=None,
    max_logs=0,
    flex_2d=True
)

Same as flex_simulate_nb(), but iterates using row-major order, with the rows changing fastest, and the columns/groups changing slowest.


generate_stop_signal_nb function

generate_stop_signal_nb(
    position_now,
    upon_stop_exit,
    accumulate
)

Generate stop signal and change accumulation if needed.


get_col_elem_nb function

get_col_elem_nb(
    ctx,
    col,
    a
)

Get the current element using flexible indexing given the context and the column.


get_elem_nb function

get_elem_nb(
    ctx,
    a
)

Get the current element using flexible indexing given just the context.


get_entry_trades_nb function

get_entry_trades_nb(
    order_records,
    close,
    col_map
)

Fill entry trade records by aggregating order records.

Entry trade records are buy orders in a long position and sell orders in a short position.

Usage

>>> import numpy as np
>>> import pandas as pd
>>> from numba import njit
>>> from vectorbt.records.nb import col_map_nb
>>> from vectorbt.portfolio.nb import simulate_from_orders_nb, get_entry_trades_nb

>>> close = order_price = np.array([
...     [1, 6],
...     [2, 5],
...     [3, 4],
...     [4, 3],
...     [5, 2],
...     [6, 1]
... ])
>>> size = np.asarray([
...     [1, -1],
...     [0.1, -0.1],
...     [-1, 1],
...     [-0.1, 0.1],
...     [1, -1],
...     [-2, 2]
... ])
>>> target_shape = close.shape
>>> group_lens = np.full(target_shape[1], 1)
>>> init_cash = np.full(target_shape[1], 100)
>>> call_seq = np.full(target_shape, 0)

>>> order_records, log_records = simulate_from_orders_nb(
...     target_shape,
...     group_lens,
...     init_cash,
...     call_seq,
...     size=size,
...     price=close,
...     fees=np.asarray(0.01),
...     slippage=np.asarray(0.01)
... )

>>> col_map = col_map_nb(order_records['col'], target_shape[1])
>>> entry_trade_records = get_entry_trades_nb(order_records, close, col_map)
>>> pd.DataFrame.from_records(entry_trade_records)
   id  col  size  entry_idx  entry_price  entry_fees  exit_idx  exit_price  \
0   0    0   1.0          0         1.01     0.01010         3    3.060000
1   1    0   0.1          1         2.02     0.00202         3    3.060000
2   2    0   1.0          4         5.05     0.05050         5    5.940000
3   3    0   1.0          5         5.94     0.05940         5    6.000000
4   4    1   1.0          0         5.94     0.05940         3    3.948182
5   5    1   0.1          1         4.95     0.00495         3    3.948182
6   6    1   1.0          4         1.98     0.01980         5    1.010000
7   7    1   1.0          5         1.01     0.01010         5    1.000000

   exit_fees       pnl    return  direction  status  parent_id
0   0.030600  2.009300  1.989406          0       1          0
1   0.003060  0.098920  0.489703          0       1          0
2   0.059400  0.780100  0.154475          0       1          1
3   0.000000 -0.119400 -0.020101          1       0          2
4   0.039482  1.892936  0.318676          1       1          3
5   0.003948  0.091284  0.184411          1       1          3
6   0.010100  0.940100  0.474798          1       1          4
7   0.000000 -0.020100 -0.019901          0       0          5

get_exit_trades_nb function

get_exit_trades_nb(
    order_records,
    close,
    col_map
)

Fill exit trade records by aggregating order records.

Exit trade records are sell orders in a long position and buy orders in a short position.

Usage

>>> import numpy as np
>>> import pandas as pd
>>> from numba import njit
>>> from vectorbt.records.nb import col_map_nb
>>> from vectorbt.portfolio.nb import simulate_from_orders_nb, get_exit_trades_nb

>>> close = order_price = np.array([
...     [1, 6],
...     [2, 5],
...     [3, 4],
...     [4, 3],
...     [5, 2],
...     [6, 1]
... ])
>>> size = np.asarray([
...     [1, -1],
...     [0.1, -0.1],
...     [-1, 1],
...     [-0.1, 0.1],
...     [1, -1],
...     [-2, 2]
... ])
>>> target_shape = close.shape
>>> group_lens = np.full(target_shape[1], 1)
>>> init_cash = np.full(target_shape[1], 100)
>>> call_seq = np.full(target_shape, 0)

>>> order_records, log_records = simulate_from_orders_nb(
...     target_shape,
...     group_lens,
...     init_cash,
...     call_seq,
...     size=size,
...     price=close,
...     fees=np.asarray(0.01),
...     slippage=np.asarray(0.01)
... )

>>> col_map = col_map_nb(order_records['col'], target_shape[1])
>>> exit_trade_records = get_exit_trades_nb(order_records, close, col_map)
>>> pd.DataFrame.from_records(exit_trade_records)
   id  col  size  entry_idx  entry_price  entry_fees  exit_idx  exit_price  \
0   0    0   1.0          0     1.101818    0.011018         2        2.97
1   1    0   0.1          0     1.101818    0.001102         3        3.96
2   2    0   1.0          4     5.050000    0.050500         5        5.94
3   3    0   1.0          5     5.940000    0.059400         5        6.00
4   4    1   1.0          0     5.850000    0.058500         2        4.04
5   5    1   0.1          0     5.850000    0.005850         3        3.03
6   6    1   1.0          4     1.980000    0.019800         5        1.01
7   7    1   1.0          5     1.010000    0.010100         5        1.00

   exit_fees       pnl    return  direction  status  parent_id
0    0.02970  1.827464  1.658589          0       1          0
1    0.00396  0.280756  2.548119          0       1          0
2    0.05940  0.780100  0.154475          0       1          1
3    0.00000 -0.119400 -0.020101          1       0          2
4    0.04040  1.711100  0.292496          1       1          3
5    0.00303  0.273120  0.466872          1       1          3
6    0.01010  0.940100  0.474798          1       1          4
7    0.00000 -0.020100 -0.019901          0       0          5

get_free_cash_diff_nb function

get_free_cash_diff_nb(
    position_before,
    position_now,
    debt_now,
    price,
    fees
)

Get updated debt and free cash flow.


get_group_value_ctx_nb function

get_group_value_ctx_nb(
    seg_ctx
)

Get group value from context.

Accepts SegmentContext.

Best called once from pre_segment_func_nb. To set the valuation price, change last_val_price of the context in-place.

Note

Cash sharing must be enabled.


get_group_value_nb function

get_group_value_nb(
    from_col,
    to_col,
    cash_now,
    last_position,
    last_val_price
)

Get group value.


get_long_size_nb function

get_long_size_nb(
    position_before,
    position_now
)

Get long size.


get_positions_nb function

get_positions_nb(
    trade_records,
    col_map
)

Fill position records by aggregating trade records.

Trades can be entry trades, exit trades, and even positions themselves - all will produce the same results.

Usage

>>> from vectorbt.portfolio.nb import get_positions_nb

>>> col_map = col_map_nb(exit_trade_records['col'], target_shape[1])
>>> position_records = get_positions_nb(exit_trade_records, col_map)
>>> pd.DataFrame.from_records(position_records)
   id  col  size  entry_idx  entry_price  entry_fees  exit_idx  exit_price  \
0   0    0   1.1          0     1.101818     0.01212         3    3.060000
1   1    0   1.0          4     5.050000     0.05050         5    5.940000
2   2    0   1.0          5     5.940000     0.05940         5    6.000000
3   3    1   1.1          0     5.850000     0.06435         3    3.948182
4   4    1   1.0          4     1.980000     0.01980         5    1.010000
5   5    1   1.0          5     1.010000     0.01010         5    1.000000

   exit_fees      pnl    return  direction  status  parent_id
0    0.03366  2.10822  1.739455          0       1          0
1    0.05940  0.78010  0.154475          0       1          1
2    0.00000 -0.11940 -0.020101          1       0          2
3    0.04343  1.98422  0.308348          1       1          3
4    0.01010  0.94010  0.474798          1       1          4
5    0.00000 -0.02010 -0.019901          0       0          5

get_short_size_nb function

get_short_size_nb(
    position_before,
    position_now
)

Get short size.


get_stop_price_nb function

get_stop_price_nb(
    position_now,
    stop_price,
    stop,
    open,
    low,
    high,
    hit_below
)

Get stop price.

If hit before open, returns open.


get_trade_stats_nb function

get_trade_stats_nb(
    size,
    entry_price,
    entry_fees,
    exit_price,
    exit_fees,
    direction
)

Get trade statistics.


gross_exposure_nb function

gross_exposure_nb(
    asset_value,
    cash
)

Get gross exposure per column/group.


group_mean_reduce_nb function

group_mean_reduce_nb(
    group,
    a
)

Mean reducer for grouped columns.


i_group_any_reduce_nb function

i_group_any_reduce_nb(
    i,
    group,
    a
)

Boolean "any" reducer for grouped columns.


init_cash_grouped_nb function

init_cash_grouped_nb(
    init_cash,
    group_lens,
    cash_sharing
)

Get initial cash per group.


init_cash_nb function

init_cash_nb(
    init_cash,
    group_lens,
    cash_sharing
)

Get initial cash per column.


init_records_nb function

init_records_nb(
    target_shape,
    max_orders=None,
    max_logs=0
)

Initialize order and log records.


is_grouped_nb function

is_grouped_nb(
    group_lens
)

Check if columm,ns are grouped, that is, more than one column per group.


ls_enex_signal_func_nb function

ls_enex_signal_func_nb(
    c,
    long_entries,
    long_exits,
    short_entries,
    short_exits
)

Get an element of direction-aware signals.


no_adjust_sl_func_nb function

no_adjust_sl_func_nb(
    c,
    *args
)

Placeholder function that returns the initial stop-loss value and trailing flag.


no_adjust_tp_func_nb function

no_adjust_tp_func_nb(
    c,
    *args
)

Placeholder function that returns the initial take-profit value.


no_flex_order_func_nb function

no_flex_order_func_nb(
    c,
    *args
)

Placeholder flexible order function that returns break column and no order.


no_order_func_nb function

no_order_func_nb(
    c,
    *args
)

Placeholder order function that returns no order.


no_post_func_nb function

no_post_func_nb(
    c,
    *args
)

Placeholder postprocessing function that returns nothing.


no_pre_func_nb function

no_pre_func_nb(
    c,
    *args
)

Placeholder preprocessing function that forwards received arguments down the stack.


no_signal_func_nb function

no_signal_func_nb(
    c,
    *args
)

Placeholder signal function that returns no signal.


order_nb function

order_nb(
    size=nan,
    price=inf,
    size_type=0,
    direction=2,
    fees=0.0,
    fixed_fees=0.0,
    slippage=0.0,
    min_size=0.0,
    max_size=inf,
    size_granularity=nan,
    reject_prob=0.0,
    lock_cash=False,
    allow_partial=True,
    raise_reject=False,
    log=False
)

Create an order.

See Order for details on arguments.


order_not_filled_nb function

order_not_filled_nb(
    status,
    status_info
)

Return OrderResult for order that hasn't been filled.


order_nothing_nb function

order_nothing_nb()

Convenience function to order nothing.


position_coverage_grouped_nb function

position_coverage_grouped_nb(
    position_mask,
    group_lens
)

Get coverage of position for each row and group.


position_mask_grouped_nb function

position_mask_grouped_nb(
    position_mask,
    group_lens
)

Get whether in position for each row and group.


process_order_nb function

process_order_nb(
    i,
    col,
    group,
    state,
    update_value,
    order,
    order_records,
    log_records
)

Process an order by executing it, saving relevant information to the logs, and returning a new state.


raise_rejected_order_nb function

raise_rejected_order_nb(
    order_result
)

Raise an RejectedOrderError.


replace_inf_price_nb function

replace_inf_price_nb(
    prev_close,
    close,
    order
)

Replace infinity price in an order.


require_call_seq function

require_call_seq(
    call_seq
)

Force the call sequence array to pass our requirements.


resolve_dir_conflict_nb function

resolve_dir_conflict_nb(
    position_now,
    is_long_entry,
    is_short_entry,
    upon_dir_conflict
)

Resolve any direction conflict between a long entry and a short entry.


resolve_opposite_entry_nb function

resolve_opposite_entry_nb(
    position_now,
    is_long_entry,
    is_long_exit,
    is_short_entry,
    is_short_exit,
    upon_opposite_entry,
    accumulate
)

Resolve opposite entry.


resolve_signal_conflict_nb function

resolve_signal_conflict_nb(
    position_now,
    is_entry,
    is_exit,
    direction,
    conflict_mode
)

Resolve any conflict between an entry and an exit.


resolve_stop_price_and_slippage_nb function

resolve_stop_price_and_slippage_nb(
    stop_price,
    price,
    close,
    slippage,
    stop_exit_price
)

Resolve price and slippage of a stop order.


returns_in_sim_order_nb function

returns_in_sim_order_nb(
    value_iso,
    group_lens,
    init_cash_grouped,
    call_seq
)

Get portfolio return series in simulation order.


sell_nb function

sell_nb(
    exec_state,
    size,
    price,
    direction=2,
    fees=0.0,
    fixed_fees=0.0,
    slippage=0.0,
    min_size=0.0,
    max_size=inf,
    size_granularity=nan,
    lock_cash=False,
    allow_partial=True,
    percent=nan
)

Sell or/and short sell.


should_update_stop_nb function

should_update_stop_nb(
    stop,
    upon_stop_update
)

Whether to update stop.


shuffle_call_seq_nb function

shuffle_call_seq_nb(
    call_seq,
    group_lens
)

Shuffle the call sequence array.


signals_to_size_nb function

signals_to_size_nb(
    position_now,
    is_long_entry,
    is_long_exit,
    is_short_entry,
    is_short_exit,
    size,
    size_type,
    accumulate,
    val_price_now
)

Translate direction-aware signals into size, size type, and direction.


simulate_from_orders_nb function

simulate_from_orders_nb(
    target_shape,
    group_lens,
    init_cash,
    call_seq,
    size=array(inf),
    price=array(inf),
    size_type=array(0),
    direction=array(2),
    fees=array(0.),
    fixed_fees=array(0.),
    slippage=array(0.),
    min_size=array(0.),
    max_size=array(inf),
    size_granularity=array(nan),
    reject_prob=array(0.),
    lock_cash=array(False),
    allow_partial=array(True),
    raise_reject=array(False),
    log=array(False),
    val_price=array(inf),
    close=array(nan),
    auto_call_seq=False,
    ffill_val_price=True,
    update_value=False,
    max_orders=None,
    max_logs=0,
    flex_2d=True
)

Creates on order out of each element.

Iterates in the column-major order. Utilizes flexible broadcasting.

Note

Should be only grouped if cash sharing is enabled.

If auto_call_seq is True, make sure that call_seq follows CallSeqType.Default.

Single value should be passed as a 0-dim array (for example, by using np.asarray(value)).

Usage

  • Buy and hold using all cash and closing price (default):
>>> import numpy as np
>>> from vectorbt.records.nb import col_map_nb
>>> from vectorbt.portfolio.nb import simulate_from_orders_nb, asset_flow_nb
>>> from vectorbt.portfolio.enums import Direction

>>> close = np.array([1, 2, 3, 4, 5])[:, None]
>>> order_records, _ = simulate_from_orders_nb(
...     target_shape=close.shape,
...     close=close,
...     group_lens=np.array([1]),
...     init_cash=np.array([100]),
...     call_seq=np.full(close.shape, 0)
... )
>>> col_map = col_map_nb(order_records['col'], close.shape[1])
>>> asset_flow = asset_flow_nb(close.shape, order_records, col_map, Direction.Both)
>>> asset_flow
array([[100.],
       [  0.],
       [  0.],
       [  0.],
       [  0.]])

simulate_from_signal_func_nb function

simulate_from_signal_func_nb(
    target_shape,
    group_lens,
    init_cash,
    call_seq,
    signal_func_nb=no_signal_func_nb,
    signal_args=(),
    size=array(inf),
    price=array(inf),
    size_type=array(0),
    fees=array(0.),
    fixed_fees=array(0.),
    slippage=array(0.),
    min_size=array(0.),
    max_size=array(inf),
    size_granularity=array(nan),
    reject_prob=array(0.),
    lock_cash=array(False),
    allow_partial=array(True),
    raise_reject=array(False),
    log=array(False),
    accumulate=array(0),
    upon_long_conflict=array(0),
    upon_short_conflict=array(0),
    upon_dir_conflict=array(0),
    upon_opposite_entry=array(4),
    val_price=array(inf),
    open=array(nan),
    high=array(nan),
    low=array(nan),
    close=array(nan),
    sl_stop=array(nan),
    sl_trail=array(False),
    tp_stop=array(nan),
    stop_entry_price=array(3),
    stop_exit_price=array(0),
    upon_stop_exit=array(0),
    upon_stop_update=array(1),
    adjust_sl_func_nb=no_adjust_sl_func_nb,
    adjust_sl_args=(),
    adjust_tp_func_nb=no_adjust_tp_func_nb,
    adjust_tp_args=(),
    use_stops=True,
    auto_call_seq=False,
    ffill_val_price=True,
    update_value=False,
    max_orders=None,
    max_logs=0,
    flex_2d=True
)

Creates an order out of each element by resolving entry and exit signals returned by signal_func_nb.

Iterates in the column-major order. Utilizes flexible broadcasting.

Signals are processed using the following pipeline:

1) If there is a stop signal, convert it to direction-aware signals and proceed to 7) 2) Get direction-aware signals using signal_func_nb 3) Resolve any entry and exit conflict of each direction using resolve_signal_conflict_nb() 4) Resolve any direction conflict using resolve_dir_conflict_nb() 5) Resolve an opposite entry signal scenario using resolve_opposite_entry_nb() 7) Convert the final signals into size, size type, and direction using signals_to_size_nb()

Note

Should be only grouped if cash sharing is enabled.

If auto_call_seq is True, make sure that call_seq follows CallSeqType.Default.

Single value should be passed as a 0-dim array (for example, by using np.asarray(value)).

Usage

  • Buy and hold using all cash and closing price (default):
>>> import numpy as np
>>> from vectorbt.records.nb import col_map_nb
>>> from vectorbt.portfolio import nb
>>> from vectorbt.portfolio.enums import Direction

>>> close = np.array([1, 2, 3, 4, 5])[:, None]
>>> order_records, _ = nb.simulate_from_signal_func_nb(
...     target_shape=close.shape,
...     close=close,
...     group_lens=np.array([1]),
...     init_cash=np.array([100]),
...     call_seq=np.full(close.shape, 0),
...     signal_func_nb=nb.dir_enex_signal_func_nb,
...     signal_args=(np.asarray(True), np.asarray(False), np.asarray(Direction.LongOnly))
... )
>>> col_map = col_map_nb(order_records['col'], close.shape[1])
>>> asset_flow = nb.asset_flow_nb(close.shape, order_records, col_map, Direction.Both)
>>> asset_flow
array([[100.],
       [  0.],
       [  0.],
       [  0.],
       [  0.]])

simulate_nb function

simulate_nb(
    target_shape,
    group_lens,
    init_cash,
    cash_sharing,
    call_seq,
    segment_mask=array(True),
    call_pre_segment=False,
    call_post_segment=False,
    pre_sim_func_nb=no_pre_func_nb,
    pre_sim_args=(),
    post_sim_func_nb=no_post_func_nb,
    post_sim_args=(),
    pre_group_func_nb=no_pre_func_nb,
    pre_group_args=(),
    post_group_func_nb=no_post_func_nb,
    post_group_args=(),
    pre_segment_func_nb=no_pre_func_nb,
    pre_segment_args=(),
    post_segment_func_nb=no_post_func_nb,
    post_segment_args=(),
    order_func_nb=no_order_func_nb,
    order_args=(),
    post_order_func_nb=no_post_func_nb,
    post_order_args=(),
    close=array(nan),
    ffill_val_price=True,
    update_value=False,
    fill_pos_record=True,
    max_orders=None,
    max_logs=0,
    flex_2d=True
)

Fill order and log records by iterating over a shape and calling a range of user-defined functions.

Starting with initial cash init_cash, iterates over each group and column in target_shape, and for each data point, generates an order using order_func_nb. Tries then to fulfill that order. Upon success, updates the current state including the cash balance and the position.

Returns order records of layout order_dt and log records of layout log_dt.

As opposed to simulate_row_wise_nb(), order processing happens in column-major order. Column-major order means processing the entire column/group with all rows before moving to the next one. See Row- and column-major order.

Args

target_shape : tuple
See SimulationContext.target_shape.
group_lens : array_like of int
See SimulationContext.group_lens.
init_cash : array_like of float
See SimulationContext.init_cash.
cash_sharing : bool
See SimulationContext.cash_sharing.
call_seq : array_like of int
See SimulationContext.call_seq.
segment_mask : array_like of bool
See SimulationContext.segment_mask.
call_pre_segment : bool
See SimulationContext.call_pre_segment.
call_post_segment : bool
See SimulationContext.call_post_segment.
pre_sim_func_nb : callable

Function called before simulation.

Can be used for creation of global arrays and setting the seed.

Should accept SimulationContext and *pre_sim_args. Should return a tuple of any content, which is then passed to pre_group_func_nb and post_group_func_nb.

pre_sim_args : tuple
Packed arguments passed to pre_sim_func_nb.
post_sim_func_nb : callable

Function called after simulation.

Should accept SimulationContext and *post_sim_args. Should return nothing.

post_sim_args : tuple
Packed arguments passed to post_sim_func_nb.
pre_group_func_nb : callable

Function called before each group.

Should accept GroupContext, unpacked tuple from pre_sim_func_nb, and *pre_group_args. Should return a tuple of any content, which is then passed to pre_segment_func_nb and post_segment_func_nb.

pre_group_args : tuple
Packed arguments passed to pre_group_func_nb.
post_group_func_nb : callable

Function called after each group.

Should accept GroupContext, unpacked tuple from pre_sim_func_nb, and *post_group_args. Should return nothing.

post_group_args : tuple
Packed arguments passed to post_group_func_nb.
pre_segment_func_nb : callable

Function called before each segment.

Called if segment_mask or call_pre_segment is True.

Should accept SegmentContext, unpacked tuple from pre_group_func_nb, and *pre_segment_args. Should return a tuple of any content, which is then passed to order_func_nb and post_order_func_nb.

This is the right place to change call sequence and set the valuation price. Group re-valuation and update of the open position stats happens right after this function, regardless of whether it has been called.

Note

To change the call sequence of a segment, access SegmentContext.call_seq_now and change it in-place. Make sure to not generate any new arrays as it may negatively impact performance. Assigning SegmentContext.call_seq_now as any other context (named tuple) value is not supported. See SegmentContext.call_seq_now.

Note

You can override elements of last_val_price to manipulate group valuation. See SimulationContext.last_val_price.

pre_segment_args : tuple
Packed arguments passed to pre_segment_func_nb.
post_segment_func_nb : callable

Function called after each segment.

Called if segment_mask or call_post_segment is True.

The last group re-valuation and update of the open position stats happens right before this function, regardless of whether it has been called.

Should accept SegmentContext, unpacked tuple from pre_group_func_nb, and *post_segment_args. Should return nothing.

post_segment_args : tuple
Packed arguments passed to post_segment_func_nb.
order_func_nb : callable

Order generation function.

Used for either generating an order or skipping.

Should accept OrderContext, unpacked tuple from pre_segment_func_nb, and *order_args. Should return Order.

Note

If the returned order has been rejected, there is no way of issuing a new order. You should make sure that the order passes, for example, by using try_order_nb().

To have a greater freedom in order management, use flex_simulate_nb().

order_args : tuple
Arguments passed to order_func_nb.
post_order_func_nb : callable

Callback that is called after the order has been processed.

Used for checking the order status and doing some post-processing.

Should accept PostOrderContext, unpacked tuple from pre_segment_func_nb, and *post_order_args. Should return nothing.

post_order_args : tuple
Arguments passed to post_order_func_nb.
close : array_like of float
See SimulationContext.close.
ffill_val_price : bool
See SimulationContext.ffill_val_price.
update_value : bool
See SimulationContext.update_value.
fill_pos_record : bool
See SimulationContext.fill_pos_record.
max_orders : int
Size of the order records array.
max_logs : int
Size of the log records array.
flex_2d : bool
See SimulationContext.flex_2d.

Note

Remember that indexing of 2-dim arrays in vectorbt follows that of pandas: a[i, col].

Warning

You can only safely access data of columns that are to the left of the current group and rows that are to the top of the current row within the same group. Other data points have not been processed yet and thus empty. Accessing them will not trigger any errors or warnings, but provide you with arbitrary data (see np.empty).

Call hierarchy

Like most things in the vectorbt universe, simulation is also done by iterating over a (imaginary) frame. This frame consists of two dimensions: time (rows) and assets/features (columns). Each element of this frame is a potential order, which gets generated by calling an order function.

The question is: how do we move across this frame to simulate trading? There are two movement patterns: column-major (as done by simulate_nb()) and row-major order (as done by simulate_row_wise_nb()). In each of these patterns, we are always moving from top to bottom (time axis) and from left to right (asset/feature axis); the only difference between them is across which axis we are moving faster: do we want to process each column first (thus assuming that columns are independent) or each row? Choosing between them is mostly a matter of preference, but it also makes different data being available when generating an order.

The frame is further divided into "blocks": columns, groups, rows, segments, and elements. For example, columns can be grouped into groups that may or may not share the same capital. Regardless of capital sharing, each collection of elements within a group and a time step is called a segment, which simply defines a single context (such as shared capital) for one or multiple orders. Each segment can also define a custom sequence (a so-called call sequence) in which orders are executed.

You can imagine each of these blocks as a rectangle drawn over different parts of the frame, and having its own context and pre/post-processing function. The pre-processing function is a simple callback that is called before entering the block, and can be provided by the user to, for example, prepare arrays or do some custom calculations. It must return a tuple (can be empty) that is then unpacked and passed as arguments to the pre- and postprocessing function coming next in the call hierarchy. The postprocessing function can be used, for example, to write user-defined arrays such as returns.

Let's demonstrate a frame with one group of two columns and one group of one column, and the following call sequence:

array([[0, 1, 0],
       [1, 0, 0]])

And here is the context information available at each step:

Usage

  • Create a group of three assets together sharing 100$ and simulate an equal-weighted portfolio that rebalances every second tick, all without leaving Numba:
>>> import numpy as np
>>> import pandas as pd
>>> from collections import namedtuple
>>> from numba import njit
>>> from vectorbt.generic.plotting import Scatter
>>> from vectorbt.records.nb import col_map_nb
>>> from vectorbt.portfolio.enums import SizeType, Direction
>>> from vectorbt.portfolio.nb import (
...     get_col_elem_nb,
...     get_elem_nb,
...     order_nb,
...     simulate_nb,
...     simulate_row_wise_nb,
...     build_call_seq,
...     sort_call_seq_nb,
...     asset_flow_nb,
...     assets_nb,
...     asset_value_nb
... )

>>> @njit
... def pre_sim_func_nb(c):
...     print('before simulation')
...     # Create a temporary array and pass it down the stack
...     order_value_out = np.empty(c.target_shape[1], dtype=np.float_)
...     return (order_value_out,)

>>> @njit
... def pre_group_func_nb(c, order_value_out):
...     print('\tbefore group', c.group)
...     # Forward down the stack (you can omit pre_group_func_nb entirely)
...     return (order_value_out,)

>>> @njit
... def pre_segment_func_nb(c, order_value_out, size, price, size_type, direction):
...     print('\t\tbefore segment', c.i)
...     for col in range(c.from_col, c.to_col):
...         # Here we use order price for group valuation
...         c.last_val_price[col] = get_col_elem_nb(c, col, price)
...
...     # Reorder call sequence of this segment such that selling orders come first and buying last
...     # Rearranges c.call_seq_now based on order value (size, size_type, direction, and val_price)
...     # Utilizes flexible indexing using get_col_elem_nb (as we did above)
...     sort_call_seq_nb(c, size, size_type, direction, order_value_out[c.from_col:c.to_col])
...     # Forward nothing
...     return ()

>>> @njit
... def order_func_nb(c, size, price, size_type, direction, fees, fixed_fees, slippage):
...     print('\t\t\tcreating order', c.call_idx, 'at column', c.col)
...     # Create and return an order
...     return order_nb(
...         size=get_elem_nb(c, size),
...         price=get_elem_nb(c, price),
...         size_type=get_elem_nb(c, size_type),
...         direction=get_elem_nb(c, direction),
...         fees=get_elem_nb(c, fees),
...         fixed_fees=get_elem_nb(c, fixed_fees),
...         slippage=get_elem_nb(c, slippage)
...     )

>>> @njit
... def post_order_func_nb(c):
...     print('\t\t\t\torder status:', c.order_result.status)
...     return None

>>> @njit
... def post_segment_func_nb(c, order_value_out):
...     print('\t\tafter segment', c.i)
...     return None

>>> @njit
... def post_group_func_nb(c, order_value_out):
...     print('\tafter group', c.group)
...     return None

>>> @njit
... def post_sim_func_nb(c):
...     print('after simulation')
...     return None

>>> target_shape = (5, 3)
>>> np.random.seed(42)
>>> group_lens = np.array([3])  # one group of three columns
>>> init_cash = np.array([100.])  # one capital per group
>>> cash_sharing = True
>>> call_seq = build_call_seq(target_shape, group_lens)  # will be overridden
>>> segment_mask = np.array([True, False, True, False, True])[:, None]
>>> segment_mask = np.copy(np.broadcast_to(segment_mask, target_shape))
>>> size = np.asarray(1 / target_shape[1])  # scalars must become 0-dim arrays
>>> price = close = np.random.uniform(1, 10, size=target_shape)
>>> size_type = np.asarray(SizeType.TargetPercent)
>>> direction = np.asarray(Direction.LongOnly)
>>> fees = np.asarray(0.001)
>>> fixed_fees = np.asarray(1.)
>>> slippage = np.asarray(0.001)

>>> order_records, log_records = simulate_nb(
...     target_shape,
...     group_lens,
...     init_cash,
...     cash_sharing,
...     call_seq,
...     segment_mask=segment_mask,
...     pre_sim_func_nb=pre_sim_func_nb,
...     post_sim_func_nb=post_sim_func_nb,
...     pre_group_func_nb=pre_group_func_nb,
...     post_group_func_nb=post_group_func_nb,
...     pre_segment_func_nb=pre_segment_func_nb,
...     pre_segment_args=(size, price, size_type, direction),
...     post_segment_func_nb=post_segment_func_nb,
...     order_func_nb=order_func_nb,
...     order_args=(size, price, size_type, direction, fees, fixed_fees, slippage),
...     post_order_func_nb=post_order_func_nb
... )
before simulation
    before group 0
        before segment 0
            creating order 0 at column 0
                order status: 0
            creating order 1 at column 1
                order status: 0
            creating order 2 at column 2
                order status: 0
        after segment 0
        before segment 2
            creating order 0 at column 1
                order status: 0
            creating order 1 at column 2
                order status: 0
            creating order 2 at column 0
                order status: 0
        after segment 2
        before segment 4
            creating order 0 at column 0
                order status: 0
            creating order 1 at column 2
                order status: 0
            creating order 2 at column 1
                order status: 0
        after segment 4
    after group 0
after simulation

>>> pd.DataFrame.from_records(order_records)
   id  col  idx       size     price      fees  side
0   0    0    0   7.626262  4.375232  1.033367     0
1   1    1    0   3.488053  9.565985  1.033367     0
2   2    2    0   3.972040  7.595533  1.030170     0
3   3    1    2   0.920352  8.786790  1.008087     1
4   4    2    2   0.448747  6.403625  1.002874     1
5   5    0    2   5.210115  1.524275  1.007942     0
6   6    0    4   7.899568  8.483492  1.067016     1
7   7    2    4  12.378281  2.639061  1.032667     0
8   8    1    4  10.713236  2.913963  1.031218     0

>>> call_seq
array([[0, 1, 2],
       [0, 1, 2],
       [1, 2, 0],
       [0, 1, 2],
       [0, 2, 1]])

>>> col_map = col_map_nb(order_records['col'], target_shape[1])
>>> asset_flow = asset_flow_nb(target_shape, order_records, col_map, Direction.Both)
>>> assets = assets_nb(asset_flow)
>>> asset_value = asset_value_nb(close, assets)
>>> Scatter(data=asset_value).fig.show()

Note that the last order in a group with cash sharing is always disadvantaged as it has a bit less funds than the previous orders due to costs, which are not included when valuating the group.


simulate_row_wise_nb function

simulate_row_wise_nb(
    target_shape,
    group_lens,
    init_cash,
    cash_sharing,
    call_seq,
    segment_mask=array(True),
    call_pre_segment=False,
    call_post_segment=False,
    pre_sim_func_nb=no_pre_func_nb,
    pre_sim_args=(),
    post_sim_func_nb=no_post_func_nb,
    post_sim_args=(),
    pre_row_func_nb=no_pre_func_nb,
    pre_row_args=(),
    post_row_func_nb=no_post_func_nb,
    post_row_args=(),
    pre_segment_func_nb=no_pre_func_nb,
    pre_segment_args=(),
    post_segment_func_nb=no_post_func_nb,
    post_segment_args=(),
    order_func_nb=no_order_func_nb,
    order_args=(),
    post_order_func_nb=no_post_func_nb,
    post_order_args=(),
    close=array(nan),
    ffill_val_price=True,
    update_value=False,
    fill_pos_record=True,
    max_orders=None,
    max_logs=0,
    flex_2d=True
)

Same as simulate_nb(), but iterates in row-major order.

Row-major order means processing the entire row with all groups/columns before moving to the next one.

The main difference is that instead of pre_group_func_nb it now exposes pre_row_func_nb, which is executed per entire row. It should accept RowContext.

Note

Function pre_row_func_nb is only called if there is at least on active segment in the row. Functions pre_segment_func_nb and order_func_nb are only called if their segment is active. If the main task of pre_row_func_nb is to activate/deactivate segments, all segments should be activated by default to allow pre_row_func_nb to be called.

Warning

You can only safely access data points that are to the left of the current group and rows that are to the top of the current row.

Call hierarchy

Let's illustrate the same example as in simulate_nb() but adapted for this function:

Usage

  • Running the same example as in simulate_nb() but adapted for this function:
>>> @njit
... def pre_row_func_nb(c, order_value_out):
...     print('\tbefore row', c.i)
...     # Forward down the stack
...     return (order_value_out,)

>>> @njit
... def post_row_func_nb(c, order_value_out):
...     print('\tafter row', c.i)
...     return None

>>> call_seq = build_call_seq(target_shape, group_lens)
>>> order_records, log_records = simulate_row_wise_nb(
...     target_shape,
...     group_lens,
...     init_cash,
...     cash_sharing,
...     call_seq,
...     segment_mask=segment_mask,
...     pre_sim_func_nb=pre_sim_func_nb,
...     post_sim_func_nb=post_sim_func_nb,
...     pre_row_func_nb=pre_row_func_nb,
...     post_row_func_nb=post_row_func_nb,
...     pre_segment_func_nb=pre_segment_func_nb,
...     pre_segment_args=(size, price, size_type, direction),
...     post_segment_func_nb=post_segment_func_nb,
...     order_func_nb=order_func_nb,
...     order_args=(size, price, size_type, direction, fees, fixed_fees, slippage),
...     post_order_func_nb=post_order_func_nb
... )
before simulation
    before row 0
        before segment 0
            creating order 0 at column 0
                order status: 0
            creating order 1 at column 1
                order status: 0
            creating order 2 at column 2
                order status: 0
        after segment 0
    after row 0
    before row 1
    after row 1
    before row 2
        before segment 2
            creating order 0 at column 1
                order status: 0
            creating order 1 at column 2
                order status: 0
            creating order 2 at column 0
                order status: 0
        after segment 2
    after row 2
    before row 3
    after row 3
    before row 4
        before segment 4
            creating order 0 at column 0
                order status: 0
            creating order 1 at column 2
                order status: 0
            creating order 2 at column 1
                order status: 0
        after segment 4
    after row 4
after simulation

sort_call_seq_nb function

sort_call_seq_nb(
    ctx,
    size,
    size_type,
    direction,
    order_value_out,
    ctx_select=True
)

Sort call sequence attached to SegmentContext.

See sort_call_seq_out_nb().

Note

Can only be used in non-flexible simulation functions.


sort_call_seq_out_nb function

sort_call_seq_out_nb(
    ctx,
    size,
    size_type,
    direction,
    order_value_out,
    call_seq_out,
    ctx_select=True
)

Sort call sequence call_seq_out based on the value of each potential order.

Accepts SegmentContext and other arguments, sorts call_seq_out in place, and returns nothing.

Arrays size, size_type, and direction utilize flexible indexing. If ctx_select is True, selects the elements of each size, size_type, and direction using get_col_elem_nb() assuming that each array can broadcast to target_shape. Otherwise, selects using flex_select_auto_nb() assuming that each array can broadcast to group_len.

The lengths of order_value_out and call_seq_out should match the number of columns in the group. Array order_value_out should be empty and will contain sorted order values after execution. Array call_seq_out should be filled with integers ranging from 0 to the number of columns in the group (in this exact order).

Best called once from pre_segment_func_nb.

Note

Cash sharing must be enabled and call_seq_out should follow CallSeqType.Default.

Should be used in flexible simulation functions.


sum_grouped_nb function

sum_grouped_nb(
    a,
    group_lens
)

Squeeze each group of columns into a single column using sum operation.


total_benchmark_return_nb function

total_benchmark_return_nb(
    benchmark_value
)

Get total market return per column/group.


total_profit_grouped_nb function

total_profit_grouped_nb(
    total_profit,
    group_lens
)

Get total profit per group.


total_profit_nb function

total_profit_nb(
    target_shape,
    close,
    order_records,
    col_map
)

Get total profit per column.

A much faster version than the one based on value_nb().


total_return_nb function

total_return_nb(
    total_profit,
    init_cash
)

Get total return per column/group.


trade_losing_streak_nb function

trade_losing_streak_nb(
    records
)

Return the current losing streak of each trade.


trade_winning_streak_nb function

trade_winning_streak_nb(
    records
)

Return the current winning streak of each trade.


try_order_nb function

try_order_nb(
    ctx,
    order
)

Execute an order without persistence.


update_open_pos_stats_nb function

update_open_pos_stats_nb(
    record,
    position_now,
    price
)

Update statistics of an open position record using custom price.


update_pos_record_nb function

update_pos_record_nb(
    record,
    i,
    col,
    position_before,
    position_now,
    order_result
)

Update position record after filling an order.


update_value_nb function

update_value_nb(
    cash_before,
    cash_now,
    position_before,
    position_now,
    val_price_before,
    price,
    value_before
)

Update valuation price and value.


value_in_sim_order_nb function

value_in_sim_order_nb(
    cash,
    asset_value,
    group_lens,
    call_seq
)

Get portfolio value series in simulation order.


value_nb function

value_nb(
    cash,
    asset_value
)

Get portfolio value series per column/group.