VectorBT Pro - Custom Simulator 0 : Main Functions
3 min read

VectorBT Pro - Custom Simulator 0 : Main Functions

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 the order_records and order_counts without having to manually construct them after an Order 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, or neutral) 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 the open , high , low and closing 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 🟩 or Sell 🟥.

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 the Order is set to be -closing_percent such that if 50 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 the order_records and order_counts

  • The Size component of the Order is directly linked to the precentage risk that is being taken on the account and the size_type ensures that the amount on the account that is risked is exactly as what has been specified in the function argument.