VectorBT Pro - Custom Simulator 0 : Main Functions
Importing The Dependencies
import vectorbtpro as vbt
import numpy as np
import pandas as pd
from numba import njit
import talib
import datetime as dt
import time
from collections import namedtuple
import itertools
import math
from vectorbtpro.records.nb import col_map_nb
from vectorbtpro.portfolio import nb as pf_nb, enums as pf_enums
import plotly.io as pio
from numba import njit
Order Records , Order Counts
The
order records
keep track of the details of each trade executed by a trading strategy.The purpose of order records is to provide traders with a complete record of all trades executed by the strategy, including the entry and exit prices ,order type , order size and other relevant details.
The
order counts
are the number of trades executed by a trading strategy over a certain period of time. They can be analysed to gain insights into trading activity and use this information to adjust their approach.
Process Order
The main purpose of using
vbt.pf_nb.process_order_nb
in the functions that will be introduced below is that it takes in theorder_records
andorder_counts
without having to manually construct them after anOrder
has been submitted.
Enter Position
The enter_position
will enter either a Buy
or Sell
position depending on the logic and overall structure of your strategy.
Its primary purpose is to create the Order
corresponding to the percentage_risk
and the direction
that has been specified.
It takes in a multitude of different arguments the main ones being ;
execution_state_
The
execution_state
feature keeps track of the
current position of a trading strategy (long
,short
, orneutral
) at each time step in a trading simulation.
price_area_
The
price_area_
feature can be used when constructing an order to help determine the entry and exit points for a trade since its compromised of theopen
,high
,low
andclosing
prices at the point in time the trade was taken.
percent_risk_
The
percent_risk_
% will allow us to specify how much to risk on each trade.
direction
This is simply the direction of the trade that one wants to take whether that be
Buy
🟩 orSell
🟥.
group_ , col_ , bar_
These refer to the group , column and the current bar number of the iteration of the close prices that we are on.
@njit(nogil = True)
def enter_position(execution_state_,
price_area_,
percent_risk_ = 1,
group_ = 0 , column = 0, bar_ = None,
direction = "Buy",
update_value_ = False, order_records_ = None,
order_counts_ = None, log_records_ = None,
log_counts_ = None):
if direction == "Buy":
direction_to_take = vbt.pf_enums.Direction.LongOnly
else:
direction_to_take = vbt.pf_enums.Direction.ShortOnly
Order = pf_nb.order_nb(size = percent_risk_,
size_type = vbt.pf_enums.SizeType.ValuePercent100,
direction = direction_to_take,
price = execution_state_.val_price
)
order_result , new_execution_state = vbt.pf_nb.process_order_nb(
group = group_ ,col = column , i = bar_,
exec_state = execution_state_,
order = Order,
price_area = price_area_,
update_value = update_value_,
order_records = order_records_,
order_counts = order_counts_,
log_records = log_records_,
log_counts = log_counts_)
return order_result, new_execution_state
close_full_position
There are minor differences between each function in the close_full_position
the size is specified to be -np.inf
(Infinite size) and the direction is determined via the passed execution_state.
If the execution_state.position
is >0
(greater than zero) it indicates that we are invested in a a Buy (Long position) and if it is <0
(Less than zero) then we are invested in a Sell (Short Position).
close_partial_pos
The
close_partial_pos
intends to close the position only partially.This is useful when taking partial profits which is the basis of many algorithmic trading strategies.
The
Size
when constructing theOrder
is set to be-closing_percent
such that if50
is specified only 50% of that particular position will be closed.
@njit(nogil = True)
def close_partial_pos(execution_state_,
price_area_,
closing_percent = 50,
group_ = 0 , column = 0, bar_ = None,
update_value_ = False, order_records_ = None,
order_counts_ = None, log_records_ = None,
log_counts_ = None):
if execution_state.position > 0 :
direction_to_take = vbt.pf_enums.Direction.LongOnly
else:
direction_to_take = vbt.pf_enums.Direction.ShortOnly
Order = pf_nb.order_nb(size = -closing_percent,
size_type = vbt.pf_enums.SizeType.ValuePercent100,
direction = direction_to_take,
price = execution_state_.val_price
)
order_result , new_execution_state = vbt.pf_nb.process_order_nb(
group = group_ ,col = column , i = bar_,
exec_state = execution_state_,
order = Order,
price_area = price_area_,
update_value = update_value_,
order_records = order_records_,
order_counts = order_counts_,
log_records = log_records_,
log_counts = log_counts_)
return order_result, new_execution_state
Key Points / Summary 💡
The functions streamline the process of creating the
Order
and allow all the trades to be tracked via theorder_records
andorder_counts
The
Size
component of theOrder
is directly linked to the precentage risk that is being taken on the account and thesize_type
ensures that the amount on the account that is risked is exactly as what has been specified in the function argument.