Preliminary Quantification - "Python and Quantitative Investment from Basics to Practical Combat" - Optimal Mining Strategy

Python and quantitative investment from basics to actual combat - initial strategy

Quantitative data acquisition

Excellent mine introduction

URL link: https://uqer.datayes.com/
insert image description here

insert image description here

How to use

Register and log in, click [Start Research] - [New], and create a new notebook for writing strategies.
There is a novice guide on the page to help you get started quickly.
insert image description here
First of all, you need to get the data, click [Research Data], you can find it yourself, or you can directly search for keywords above.
insert image description here
Click on the data and the function usage code will appear, which can be copied to the notebook to run. Change the code according to the function description below to obtain the data you need.
insert image description here

Daily market data

Get the closing price and total market capitalization of Ping An Bank and Shanghai Pudong Development Bank on May 13, 2015.

DataAPI.MktEqudGet(tradeDate=u'20150513',secID=u"",ticker=["000001","600000"],field=u'secID,ticker,secShortName,tradeDate,preClosePrice,marketValue',pandas="1")

insert image description here
Data over time:

DataAPI.MktEqudGet(tradeDate=u'',secID=u"",ticker=["000001","600000"],beginDate=u"20180117",endDate=u"20180119",field=u'secID,ticker,secShortName,tradeDate,preClosePrice,marketValue',pandas="1")

insert image description here

factor data

Choose a function according to your needs
insert image description here

DataAPI.MktStockFactorsDateRangeGet(secID=u"",ticker=["000001","600000"],beginDate=u"20170612",endDate=u"20170616",field=u"secID,ticker,tradeDate,PS,PB,NetProfitGrowRate",pandas="1")

insert image description here
In addition to these commonly used financial data, the Youkuang data module also includes financial report data, event data and futures data, explore by yourself hahaha

data processing

data merge

Combination of closing price and moving average data

df_quotation=DataAPI.MktEqudGet(tradeDate=u'',secID=u"",ticker=["000001","600000"],beginDate=u"20180101",endDate=u"20180121",field=u'secID,ticker,tradeDate,closePrice',pandas="1")

df_factor=DataAPI.MktStockFactorsDateRangeGet(secID=u"",ticker=["000001","600000"],beginDate=u"20180101",endDate=u"20180121",field=u"secID,ticker,tradeDate,MA10,MA5",pandas="1")
df_quotation.merge(df_factor,on=['ticker','tradeDate'])

insert image description here

Pivot

Find the sum of the market capitalization of a stock for each day:

df_quotation=DataAPI.MktEqudGet(tradeDate=u'',secID=u"",ticker=["000001","600000"],beginDate=u"20180101",endDate=u"20180121",field=u'secID,ticker,tradeDate,closePrice,marketValue',pandas="1")
df_quotation=df_quotation.pivot_table(index='tradeDate',columns='secID',values='marketValue')
df_quotation

insert image description here

data filtering

Select data with PE>0

df=DataAPI.MktStockFactorsOneDayGet(tradeDate=u"20180119",secID=set_universe('A'),ticker=u"",field=u"secID,tradeDate,PE",pandas="1")
df[df.PE>0].head(10)

insert image description here

Data acquisition and organization

Histograms and Boxplots

df=DataAPI.MktStockFactorsOneDayGet(tradeDate=u"20180119",secID=set_universe('A'),ticker=u"",field=u"secID,tradeDate,ROE",pandas="1")
df.plot.hist(bins=100)

insert image description here

_=df.boxplot(sym='rs')

insert image description here
The data is de-extreme, and the factor modeling after processing is more stable. It is the "blocking method" often mentioned in data mining.

df_=df.copy()
df_.loc[df.ROE-df.ROE.mean()<-3*df.ROE.std(),'ROE']=df.ROE.mean()-3*df.ROE.std()
df_.loc[df.ROE-df.ROE.mean()>3*df.ROE.std(),'ROE']=df.ROE.mean()+3*df.ROE.std()
df_.plot.hist(bins=100)

insert image description here

Data Transformation: Standardized Dummy Variables

Standardized
Min-max normalized value is the same to 0-1; z-score normalized mean 0, variance 1.

((df_['ROE']-df_['ROE'].min())/(df_['ROE'].max()-df_['ROE'].min())).plot.hist(bins=100)

insert image description here

((df_['ROE']-df_['ROE'].mean())/df_['ROE'].std()).plot.hist(bins=100)

insert image description here
dummy variable

import pandas as pd
df_industry=DataAPI.EquIndustryGet(secID=df_['secID'].tolist(),ticker=u"",industryVersionCD=u"010303",industry=u"",intoDate=u"20180101",
                                   field=u"secID,industryName1",pandas="1")
industry_list=df_industry['industryName1'].drop_duplicates().tolist()
df_industry
def get(x):
    ind_s=pd.Series([0]*len(industry_list),index=industry_list)
    if len(df_industry[df_industry['secID']==x])>0:
        ind=df_industry[df_industry['secID']==x]['industryName1'].values[0]
        ind_s.loc[ind]=1
    return ind_s    
df_[industry_list]=df_['secID'].apply(lambda x:get(x))
df_.head()

insert image description here

Contact data backtest

In [Start Research], [Create], select [Strategy], and the following policy template appears:
insert image description here

Backtesting platform functions and parameter settings

For a general description of the function, read the book "Python and Quantitative Investment from Basics to Practical Combat" for details.

Set backtest parameters

start and end (set the backtest interval) : refers to the start date of the backtest
universe (securities pool) : refers to the securities pool of the strategy backtest, that is, the domain where the strategy logic works. Order placement and historical data acquisition are limited to universes securities. universe supports all A-shares and all ETFs and LOFs that can be traded in the secondary market; it also supports three ways to obtain securities pools: DynamicUniverse, set_universe and StockScreener; you can also use a fixed stock list, such as ['000001.XSHE', '600000.XSHG']. The setting of this parameter is mainly to allow the backtest platform to preload relevant data in advance to speed up the backtest.
set_universe (static securities pool) : used to return a preset list of securities codes, supporting industry constituent stocks and index constituent stocks. When an asset pool is specified as a specific list, the policy framework returns only the contents of the corresponding list.
DynamicUniverse (Dynamic Security Pool) is used to return a Dynamic Universe instance. When using sector constituent stocks, index constituent stocks or industry constituent stocks as the trading object of the strategy, the strategy framework will adjust the content of the stock pool on the day according to the actual situation.
apply_filter is used to apply the filtering conditions to the securities pool of each trading day of the dynamic securities pool, further narrowing the scope of the strategy target. Currently, all factors in the optimal mining factor library are supported to screen the securities pool.
Benchmark (reference benchmark) is the strategy reference standard, that is, the comparison standard for the backtest results of the quantitative strategy. Through comparison, you can roughly see whether the strategy is good or bad, and it is of str type. Some risk indicators of the strategy, such as alpha and beta, are also calculated through benchmarks.

freq and refresh_rate (strategy running frequency) strategy backtesting essentially uses historical market prices and other dependent data to perform historical replay of the logic of the strategy. The two functions freq and refresh_rate jointly determine the data used in the backtest and the frequency of rebalancing. Among them, freq means that the data used is daily market data or minute line market data, which is of str type; refresh_rate represents the time between rebalancing intervals, It is an int or (a, b) structure for each trigger handle_data interval.

accounts account configuration

It is the trading account configuration function of the Umine backtesting framework. The latest framework of Umine supports a variety of trading varieties, and can backtest multiple trading accounts at the same time.

AccountConfig (account configuration) is used to configure a single trading account, and the corresponding trading account will be created according to the configuration of the account when the strategy is initialized.
account_type (account type setting) is used to set the trading account type, which is str type, and supports security stocks and on-site funds, futures futures, otc_fund over-the-counter funds (excluding currency funds), and index indexes.
capital_base (initial capital setting)
position_bas (initial position setting)
cost_base (initial cost setting)
commission (handling fee setting)
slippage (slippage setting)
margin_rate (margin ratio setting)
dividend_method (fund dividend method setting)

initialize (policy initialization environment)

initialize() is a policy initialization function, which is used to configure the properties of the context object of the policy running environment or customize various variables, and it is only executed once in the policy running cycle. We can add new properties or customize various variables through context. Show

handle_data (strategy operation logic)

handle_data() is a strategy algorithm function, which will be called according to the strategy algorithm running frequency configured initially when the strategy is running (backtesting or simulated trading). The strategy algorithm can obtain the running market data, K-line chart, factor data, order book and other data through the context, and entrust the order through the trading account according to the analysis results.

context (policy execution environment)

context represents the strategy running environment, including running time, market data, etc., and can also
be used to store temporary data generated in the storage strategy.

now (the current moment when the strategy is running)
current_date (the current backtest date)
previous_date (the previous trading day of the backtest date)
current_minute (the minute value of the current operation)
current_price (get the transaction price)
get_account (get the trading account)
get_universe (get Securities pool on the current trading day)
transfer_cash (transfer of funds between accounts)

Stock Template Example

A complete stock strategy example:

The strategic idea is to select the 60 stocks with the highest cumulative yields in the past 60 trading days to buy, and the swap frequency is 60 days.
It can be seen that the final performance of the strategy is average, slightly better than the index.

import pandas as pd 
start = '2014-11-01'                       # 回测起始时间
end = '2018-01-01'                         # 回测结束时间
benchmark = 'HS300'                        # 比较基准沪深300指数
universe = DynamicUniverse('HS300')        # 股票池是动态沪深300成分股
refresh_rate=60    #调仓频率是每60个交易日调仓一次,默认频率参数是“d”天
max_history_window=60 #默认对日线数据支持30个交易日,对分钟线支持240条K线数据 
#cintext的history方法调用要确保必须max_history_window大于调用历史数据窗口

accounts = {
    
    
    'fantasy_account': AccountConfig(account_type='security', capital_base=10000000,commission=Commission(buycost=0.001,sellcost=0.002,unit='perValue'),slippage=Slippage(value=0.0,unit='perValue'))
}
#account_type='security', capital_base=10000000股票策略 初始资金1000万元
#commission参数用于设置手续费,而 slippage 参数用于设置滑点,它们接收的是特定的Commission和Slippage实例

def initialize(context):
    pass

def handle_data(context):   
    account = context.get_account('fantasy_account') #获取我们在前面设定好的股票账户
    universe = context.get_universe(exclude_halt=True)
    #context自带了一些日期属性及价量信息、股票池处理等功能。 
    #context的get_universe方法的参数exclude_halt被设置成了True,意思是获取我们当前的股票池并且剔除停牌的股票。
    #因为我们只能交易非停牌的股票,所以要把停牌的股票去掉。
    history = context.history(universe,'closePrice',60)
    #获取了各只股票在历史上 60 个交易日的前复权收盘价,格式是一个字典,键为股票代码,值是一个索引为时间、列为前复权收盘价的DataFrame。
    
    momentum = {
    
    'symbol':[],'c_ret':[]}
    for stk in history.keys():
        momentum['symbol'].append(stk)
        momentum['c_ret'].append(history[stk]['closePrice'][-1]/history[stk]['closePrice'][0])
        # 按照过去60日收益率排序,并且选择前60只的股票作为买入候选
        
#字典初始化,对每只股票进行循环,用最近的前复权价格除以60个交易日之前的前复权价格,得到累积净值。
#然后对股票按累计净值进行排序,选取前60只股票作为待买股票池。
    momentum = pd.DataFrame(momentum).sort(columns='c_ret',ascending=False).reset_index()
    #print(momentum)
    momentum=momentum[:60] 
    buylist=momentum['symbol'].tolist()
 
 #于获取策略当前的所有持仓,具体返回的是一个字典,键为股票代码,值为持仓股票数量。
#对持仓的股票进行遍历,若它不在我们的待买股票池里,就做一个order_to(stk,0)操作,意思是将该股票清仓
    for stk in account.get_positions(): 
        if stk not in buylist:
            order_to(stk,0)
      
 #把在持仓里但不在待买股票池里的股票卖出,接着也是通过account的方法account.portfolio_value获取组合的市值,然后运用 order_pct_to 方法将所有待买股票买入或卖出到等权。
#需要注意的是,通常我们都会将卖出操作写在买入操作的前面,因为只有卖出股票腾出现金,我们才可以买入其他股票
    #等权重买入所选股票
    protfolio_value=account.portfolio_value
    for stk in buylist:
        order_pct_to(stk,1.0/len(buylist))

insert image description here

history method

Used to obtain time series data such as candlestick charts. Its parameters are explained as follows.

(1) symbol: refers to the list of securities that need to be obtained, and supports a single securities or a list of securities.
(2) attribute: refers to the attribute that needs to be obtained, and supports a single value or a list of attributes. The optional range is as follows.
◎ openPrice: The opening price of the previous reinstatement.
◎ highPrice: the highest price before reinstatement.
◎ lowPrice: the lowest price before recovery.
◎ closePrice: the closing price before recovery.
◎preClosePrice: the closing price before reinstatement.
◎ turnoverVol: Turnover volume before recovery.
◎ turnoverValue: Turnover value before recovery.
(3) time_range: refers to the number of historical K-line charts that need to be traced back, corresponding to the freq attribute.
(4) freq: Refers to the K-line chart period, supporting periods such as '1d', '1m', '5m', '15m', '30m', and '60m'. '1d' means the daily line, and '1m' means the one-minute line. The minute K-line chart can only be used in minute frequency backtesting.
(5) style: refers to the type of data return, you can choose the three types of 'ast', 'sat' or 'tas', where 'a' means 'attribute', 's' means symbol, 't' means time, The three options correspond to the order in which the three dimensions are presented. For example, 'ast' means that the key in the returned dictionary is attribute, and its value is a DataFrame whose column is symbol and row time, and so on.
(6) rtype: refers to the data type of the return value. You can choose the two types of 'frame' and 'array'.

order(symbol,amount,price=0.,otype=‘market’)

Refers to entrusting orders according to the specified parameters. The order type supports market order or limit order. In the limit order, the otype must be set to "limit" and the order price must be set.
Its parameters are explained as follows.

◎ When it is a symbol, it refers to the code of the securities to be traded, and must include the suffix, among which, .XSHG is for Shanghai Securities, and .XSHE for Shenzhen Securities.
◎When it is amount, it refers to the number of securities whose securities code is symbol that needs to be traded. If it is positive, it is bought, and if it is negative, it is sold; the program will automatically round the amount down to the nearest whole hundred.
◎When it is price, it refers to the order price when placing a limit order (only available for intraday strategies).
◎When it is otype, it refers to the optional two values ​​of 'market' (market order) and 'limit' (limit order), indicating the type of trading order (only available for intraday strategies when it is limit).

order_to (symbol,amount,price=0.,otype=‘market’)

It refers to adjusting the position of a certain stock to the number of hands held by placing an order. The strategy framework will automatically calculate the difference between the current position and the target position, and place an order. It is called every time handle_data is called, and only one order_to function call is allowed at most, otherwise it may cause an error in the calculation of the order quantity.
Its parameters are explained as follows.

◎ When it is a symbol, it refers to the code of the securities to be traded, and must include the suffix, among which, .XSHG is for Shanghai Securities, and .XSHE for Shenzhen Securities.
◎ When it is amount, it refers to the number of securities whose stock code is symbol that needs to be traded. If it is positive, it is bought, and if it is negative, it is sold. The program will automatically round down the amount to the nearest whole hundred.
◎ When it is price, it refers to the order price when the limit order is placed (only available for intraday strategies).
◎ When it is otype, it refers to the two optional values ​​of 'market' (market order) and 'limit' (limit order), indicating the type of trading order (only available for intraday strategies when it is limit).

order_pct (symbol,pct)

Refers to placing an order in a certain proportion based on the current account equity. For example, if the current account has 100,000 yuan and 20% of the order is placed, 20,000 yuan will be used to calculate the maximum entrusted lot and place the order.
Its parameters are explained as follows.

◎ When it is a symbol, it refers to the code of the securities to be traded, and must include the suffix, among which, .XSHG is for Shanghai Securities, and .XSHE for Shenzhen Securities.
◎ When it is pct, it refers to the percentage of the securities whose code is symbol that needs to be traded to the current total value of the virtual account, ranging from 0 to 1, if it is positive, it is bought, and if it is negative, it is sold. The program will automatically round down the calculated order quantity to the nearest hundred.

order_pct_to(symbol,pct)

Refers to placing an order in a certain proportion based on the current account equity. The strategy framework will automatically calculate the difference between the current position and the target position, and place an order. For example, the current account has 100,000 yuan, and if you place an order of 20%, you will use 20,000 yuan to calculate the maximum entrusted lot size, which is 500 shares. If you currently hold 300 shares, place an order for 200 shares.
Its parameters are explained as follows.

◎ When it is a symbol, it refers to the code of the securities to be traded, and must include the suffix, among which, .XSHG is for Shanghai Securities, and .XSHE for Shenzhen Securities.
◎When it is pct, it refers to the percentage of the securities whose code is symbol that needs to be traded to the current total value of the virtual account, ranging from 0 to 1, if it is positive, it is bought, and if it is negative, it is sold. The program will automatically round down the calculated order quantity to the nearest hundred.

Futures Template Example

An example of a futures strategy:

The strategic idea is to buy 1 lot of CSI 300 futures when the market opens at 9:30 every day, sell and clear the position at 9:36, and make a stop loss of 5,000 yuan during this period.

universe = ['IFM0'] #策略期货合约 指沪深300期货主力
#因为一只期货的存续时间较短,所以在进行长期回测时会涉及期货品种的切换,而在优矿的期货回测内部已经帮大家做好了这个。
#将universe设置成期货主力后,在后面的handle_data中会根据日期自动切换品种。
start = '2015-01-01'                       # 回测起始时间
end = '2015-04-07'                         # 回测结束时间
capital_base = 600000                      #初始可用资金60万元
freq = 'm'                                 # 策略频率,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测
refresh_rate = 1                           # 调仓周期 调仓频率是每分钟调仓一次。
  
commission = Commission(buycost=0.0,sellcost=0.0,unit='perValue') #设置股指期货交易手续费
slippage = Slippage(value=0,unit='perValue') #设置价格滑点百分比

accounts = {
    
    
    'fantasy_account': AccountConfig(account_type='futures', capital_base=capital_base,commission=commission,slippage=slippage)
}#设置虚拟期货账户 要将‘account_type’调整为‘futures’,因为我们的账户是期货账户。这里为了简单展示,把交易费用与滑点都设置为了0。
  
def initialize(context): #初始化虚拟期货账户,一般用于设置计数器,回测辅助变量等。
    pass
  
def handle_data(context):    #回测调仓逻辑,每个调仓周期运行一次,可在此函数内实现信号生产,生产调仓指令。
    futures_account = context.get_account('fantasy_account') #拿到期货账户
    symbol = context.get_symbol(universe[0]) #拿到目前的期货主力对应的期货品种。

#context的current_minute获取当前的分钟时刻,判断其是否是9点半,如果是,则运用期货账户的order方法买入一手沪深300期货。
#需要注意的是,期货账户的下单方法要比股票多一个参数,那就是方向。因为期货既可以做多也可以做空 
    if context.current_minute == '09:30':
        futures_account.order(symbol,1,'open')
        
    #平仓   
#们在9点36分时首先通过futures_account.get_positions()获取期货账户的持仓情况,获取期货的多头持仓数量 long_amount。
#get_positions()方法返回的虽然也是一个字典,它的键是对应的期货代码,但它的值是包含持仓信息的一个实例。
    elif context.current_minute == '09:36':
        long_position = futures_account.get_positions().get(symbol,dict()).long_amount
        if long_position > 0:
            futures_account.order(symbol,-long_position,'close')
    
    #止损
#在9点36分做的就是把持有的仓位给平了。而对于止损是在 9 点半至 9点36分之间做的.
#我们首先判断目前是否有持仓,接着判断持仓是否已经亏了5000元,如果是,则提前卖出它。
    elif context.current_minute < '09:36':
        if len(futures_account.get_positions()) > 0 and futures_account.get_positions().get(symbol).today_profit<-5000:
            long_position = futures_account.get_positions().get(symbol,dict()).long_amount
            if long_position > 0:
                futures_account.order(symbol,-long_position,'close')        

insert image description here

get_symbol (get the mapping contract of the main continuous contract)


We can use the main contract time series when generating signals, but we need to use specific contracts when placing orders . If you want to get the specific contract symbol of the major contract mapping of the day, you can use the context.get_symbol method to obtain: context.get_symbol(symbol) The context.get_symbol method
is used to obtain the mapping contract of a major continuous contract and
return the mapping of the main continuous contract Contract, only applicable to futures varieties. Its parameter is smybol, which refers to the symbol of the main contract and is of str type.

mapping_changed (judging whether to switch the mapping contract of the main continuous contract)

It is used to judge whether to switch the mapping contract of a major continuous contract, and returns a Boolean value, which is only
applicable to futures varieties. Its parameter is smybol, which refers to the main contract symbol and is of type str.
An example is as follows:
bool context.mapping_changed(symbol)

get_rolling_tuple (get the specific contract before and after the change of the main continuous contract mapping relationship)

It is used to obtain the specific contracts before and after the change of the main continuous contract mapping relationship, and it is only applicable to futures
varieties. Its parameter is smybol, which refers to the main contract symbol and is of type str.
The example is as follows: context.get_rolling_tuple(symbol)
It returns as follows, which refers to the corresponding specific contract before and after the main switch, which is a string pair type:
(symbol_before,symbol_after)

switch_position (shift operation)

Refers to the operation of shifting positions, placing the same number of closing
and opening orders from symbol_before to symbol_after (including long and short positions), which is only applicable to futures products. When the parameter is
symbol_before, it refers to the contract before the position is transferred, which is of type str; when the parameter is symbol_after, it refers to the contract after the position is transferred, which is of type str.
An example is as follows:
futures_account.switch_position(symbol_before,symbol_after)

futures_account.order(symbol,amount,offset_flag,order_type=‘market’,price=0)

This function is the futures order function. Its parameters are explained as follows.

◎ When it is a symbol, it refers to the futures code to be traded. ◎ When it is offset_flag, it refers to the position opening or closing parameters. The two parameters open and close are optional
, open means opening a position, and close means closing a position. ◎ When it is amount, it refers to the number of securities whose futures code is symbol that needs to be traded, and its
positive and negative meanings need to be combined with offset_flag. If offset_flag is open, if the amount is
positive, you will open a position by buying, if it is negative, you will open a position by selling; if the offset_flag is close, if the amount is positive, you will close your position by buying, and if it is negative, you will close your position by selling.
When it is price, it refers to the order price when placing a limit order (only available for intraday strategies).
When it is otype, the two values ​​'market' (market order) and 'limit' (limit order) can be selected to indicate the type of trading order (only intraday strategies are available when it is limit).

Strategy Backtesting Details

Click [Backtest Details] to view the detailed adjustment
positions and risk-return indicators and other data given by the backtest platform.
insert image description here
insert image description here
You can also view the backtest results through the code:

bt

Refers to the backtest report, the format is pandas.DataFrame, including 6 columns such as date, cash position, security position, portfolio value, reference index return rate, transaction order list, and other columns defined by the user in observe.

bt_by_account

Refers to the backtest report, the format is pandas.DataFrame. Including 6 columns including date, cash position, securities position, portfolio value, reference index return rate, transaction order list, and other columns defined by the user in observe.

perf

Refers to the calculation of various risk and return indicators based on backtest records. The format is a dictionary, the key is the indicator name, and the value is the value of the indicator. Some are floats, and some are lists.

Strategy Risk Evaluation Indicators

Annualized Returns

Indicates the expected rate of return with an investment period of one year. The calculation formula is where
insert image description here
, pend refers to the final total assets of the strategy, pstart refers to the initial total assets of the strategy, and n refers to the number of backtest trading days.

Benchmark Returns

Indicates the reference standard annualized rate of return, the calculation formula is
insert image description here
where, Bend refers to the final value of the benchmark, Bstar refers to the initial value of the benchmark, and n refers to the number of backtest trading days.

Alpha

Indicates the unsystematic risk faced in investment. Alpha is the return obtained by investors that has nothing to do with market fluctuations, and is generally used to measure investors' investment skills. For example, if an investor earns a 12% return and their benchmark earns a 10% return, then the Alpha or value appreciation is 2%. Its calculation formula is
insert image description here
where, Pr is the annualized rate of return of the strategy, rf is the risk-free rate of return, and Br is the annualized rate of return of the benchmark.

a>0, the strategy has obtained excess returns relative to the risk
a=0, the strategy has obtained appropriate returns relative to the risks
a<0, the strategy has obtained less returns relative to the risks

Beta

Indicates the systemic risk faced in investment, reflecting the sensitivity of the strategy to changes in the broader market. For example, if a strategy has a Beta of 1.3, the strategy may rise by 1.3% when the market rises by 1%, and vice versa; if a strategy's Beta is -1.3, it means that when the market rises by 1%, the strategy may fall by 1.3% %,vice versa. The calculation formula is
insert image description here
where, pn refers to the daily rate of return of the strategy, Bn refers to the daily rate of return of the benchmark, refers to the variance of the daily rate of return of the benchmark, Cov (pn, Bn) refers to the covariance of the daily rate of return of the strategy and the benchmark daily rate of return .

Sharpe Ratio

Indicates how much excess return will be generated for each unit of total risk, and can comprehensively consider the benefits and risks of the strategy at the same time. The calculation formula is as
insert image description here
follows, where pr refers to the annualized rate of return of the strategy, rf refers to the risk-free rate of return, and σp refers to the volatility of the strategy's return.

Return volatility (Volatility)

It is used to measure the risk of assets. The greater the volatility, the higher the risk of the strategy. Its calculation formula is
insert image description here
where, n refers to the number of backtest trading days, pt refers to the strategy's daily return rate, and insert image description hererefers to the strategy's daily average return rate. insert image description hereThe calculation formula isinsert image description here

Information Ratio

It is used to measure the excess return brought by a unit of excess risk. The larger the information ratio, the higher the excess returns obtained by the strategy unit tracking error. Therefore, strategies with larger information ratios outperform funds with lower information ratios. A reasonable investment goal should be to pursue a high information ratio as much as possible while taking moderate risks. Its calculation formula is
insert image description here
where, pr refers to the annualized rate of return of the strategy, Br refers to the annualized rate of return of the benchmark, and σt refers to the annualized standard deviation of the difference between the daily return of the strategy and the difference between the daily return of the benchmark.

Maximum drawdown (Max Drawdown)

It is used to describe the worst possible situation of the strategy, and the calculation formula is as follows
insert image description here
, px and py refer to the total assets of the strategy on a certain day (the sum of securities holdings and cash), and y>x.

Turnover Rate

It is used to describe the frequency of strategy changes and the average time of holding a certain stock. The calculation formula is as follows: Among
insert image description here
them, px refers to the smaller of the total purchase value and the total sale value, and pavg refers to the average value of the virtual account.

Strategy Trading Details

Backtest transaction matching mechanism and order entrustment

During backtesting, the order matching process takes place after the handle_data function is run, which is a virtual matching based on historical real-time market conditions. Because it is a simulation of a real scene, the order will not be executed at a certain price immediately, but the transaction price and transaction time will be determined by comparing with the specific price and specific transaction volume of the real-time market.
The matching mechanism follows the principle of "orders are placed first, and the opening price is matched", that is, the order that is placed first will be tried first.

Slippage

In a real securities transaction environment, there is often a certain deviation between the point where the order is placed and the point where the final transaction is made. After the order is entrusted to the market, it will have a certain impact on the market trend. For example, the buy order will increase the market price, and the sell order will will lower the market price. Such shock costs create slippage. In order to more realistically simulate the performance of the strategy in the real market, Umine provides a slippage mode during backtesting to evaluate changes in transaction costs due to market shocks and changes in transaction prices. We can set specific slippage information by setting the slippage keyword, and the default slippage is 0.

transaction tax

Transaction taxes and fees mainly include brokerage fees and stamp duties. By default, the premium mining backtest adopts a tax of 1/1000 for buying and 2/1000 for selling. If you need to make more subtle adjustments, you can customize the tax information by setting the backtest initialization parameter commission keyword.
◎ Brokerage service fee: The order placement fee levied by the brokerage firm is currently charged bilaterally in the Chinese A-share market, and the handling fee for each brokerage firm is different.
◎ Stamp duty: It is a stamp duty levied by the state. Currently, it is unilaterally levied on the seller and not levied on the buyer. It is 0.1%.

Suspension and delisting

If the entrusted order cannot be traded on the same day, such as suspension and delisting, the order will
be rejected and become a waste order.

price limit

If the entrusted order has been up or down on the day and cannot be bought or sold, the order will remain in the pending order until the market closes.

Gap handling for continuous futures contracts

Continuous contracts are composed of different contracts, and there is a price difference between the two contracts before and after, so there are obvious price gaps in continuous contracts. When the price difference between the front and back contracts is relatively large, it will cause false signals in the strategy and cause signal distortion. Youkuang provides the price difference translation method and the pre-recovery method to process the continuous contract time series to reduce the impact of false signals. At the same time, it provides the contract index, which can directly generate signals based on the contract index.

Guess you like

Origin blog.csdn.net/qq_47326711/article/details/126972962