- Before the overall backtesting
" "================================================================================ General backtesting before ====================== ==========================================================" "#What to do before the overall backtestingdefInitialize (context): Set_params ()#1 Setting policy parametersSet_variables ()#2 Setting Intermediate variablesSet_backtest ()#3 setting back test conditions#1#Setting Policy Parametersdefset_params (): G.tc=15#adjust the position frequencyG.n=4#Number of positionsG.security = ["000001.XSHE","000002.XSHE","000006.XSHE","000007.XSHE","000009.XSHE"]#set up a stock pool#2#Set Intermediate variablesdefset_variables ():return#3#setting back test conditionsdefset_backtest (): Set_option ('Use_real_price', True)#trade with real pricesLog.set_level ('Order','Error')
" "================================================================================ daily before opening ====================== ==========================================================" "#things to do before opening every daydefBefore_trading_start (context): Set_slip_fee (context)#4#set slippage and handling fees according to different time periodsdefSet_slip_fee (context):#set the slip point to 0set_slippage (fixedslippage (0))#set fees according to different time periodsdt=Context.current_dtifDt>datetime.datetime (2013,1, 1): Set_commission (Pertrade (Buy_cost=0.0003, sell_cost=0.0013, min_cost=5)) elifDt>datetime.datetime (2011,1, 1): Set_commission (Pertrade (Buy_cost=0.001, sell_cost=0.002, min_cost=5)) elifDt>datetime.datetime (2009,1, 1): Set_commission (Pertrade (Buy_cost=0.002, sell_cost=0.003, min_cost=5)) Else: Set_commission (Pertrade (Buy_cost=0.003, sell_cost=0.004, min_cost=5))
- Daily Trading (using the two-moving average strategy as an example)
" "================================================================================ every day when trading ====================== ==========================================================" "defHandle_data (context, data):#divide the total funds into G. n parts, to be funded for each stockCapital_unit = context.portfolio.portfolio_value/G.N Tosell=Signal_stock_sell (context,data) tobuy=signal_stock_buy (context,data)#perform a sell operation to free up funds forIinchRange (len (g.security)):ifTosell[i]==1: Order_target_value (g.security[i],0)#perform a buy operation forIinchRange (len (g.security)):ifTobuy[i]==1: Order_target_value (g.security[i],capital_unit)if not(1inchTobuy)or(1inchTosell):#Log.info ("No Action Today")Send_message ("No operation today")#5#get a sell signal#Input: Context, data#Output: Sell-listdefSignal_stock_sell (context,data): Sell= [0]*Len (g.security) forIinchRange (len (g.security)):#figure out the values of the two exponential moving averages today and yesterday, we assume that the long line is 60 days, the short line is 1 days (the closing price of the previous day)(ema_long_pre,ema_long_now) = Get_ema (g.security[i],60, data) (Ema_short_pre,ema_short_now)= Get_ema (g.security[i],1, data)#If the short moving average crosses a long moving average from top to bottom, it is a dead fork signal, which marks the sell ifEma_short_now < Ema_long_now andEma_short_pre > Ema_long_pre andContext.portfolio.positions[g.security[i]].sellable_amount >0:sell[i]=1returnSell#6#get a buy signal#Input: Context, data#Output: Buy-listdefsignal_stock_buy (context,data): Buy= [0]*Len (g.security) forIinchRange (len (g.security)):#figure out the values of the two exponential moving averages today and yesterday, we assume that the long line is 60 days, the short line is 1 days (the closing price of the previous day)(ema_long_pre,ema_long_now) = Get_ema (g.security[i],60, data) (Ema_short_pre,ema_short_now)= Get_ema (g.security[i],1, data)#If the short moving average crosses the long moving average from bottom to top, it is the Golden Fork signal, which marks the buy ifEma_short_now > Ema_long_now andEma_short_pre < Ema_long_pre andContext.portfolio.positions[g.security[i]].sellable_amount = =0:buy[i]=1returnbuy#7#Calculate moving Average data#Input: Stock code-string, moving Average days-integer#output: Arithmetic mean-floating-point numberdefGet_ma (security_code,days):#to obtain the data for the days before, see APIA=attribute_history (Security_code, Days,'1d', ('Close')) #defines a local variable sum, which is used to sumsum=0#sum the closing price of the previous days forIinchRange (1,days+1): Sum+=a['Close'][-i]#The sum is divided by the number of days to get the arithmetic mean. returnsum/ Days#8#calculate exponential moving average data#Input: Stock code-string, moving exponential average number of days-integer, Data#output: Average of moving indices today and yesterday-floating pointdefGet_ema (security_code,days,data):#If there is only one day, the closing price of the previous night is the moving average ifDays==1: #get the closing price data for the previous two days, one as the moving average of the previous period, and the latter as the moving average of the current periodt = attribute_history (Security_code, 2,'1d', ('Close')) returnt['Close'][-2],t['Close'][-1] Else: #if global variable G. If the EMAS does not exist, create a variable of the dictionary type that is used to record the calculated EMA value . if 'EMAs' not inchdir (g): G.emas={} #The dictionary's keywords are uniquely identified by the stock code and the number of days, so that the exponential moving averages of different stocks or different days are tied together.key="%s%d"%(security_code,days)#If the keyword exists, the EMA has been calculated before, and the direct iteration can be ifKeyinchG.emas:#Calculate alpha ValueAlpha= (days-1.0)/(days+1.0) #get the EMA the day before (this is saved)Ema_pre=G.emas[key]#EMA Iteration CalculationEma_now=ema_pre*alpha+data[security_code].close* (1.0-Alpha)#write a new EMA valueg.emas[key]=Ema_now#two EMA values returned to the user yesterday and today return(Ema_pre,ema_now)#If the keyword does not exist, the EMA has not been calculated before, so initialize Else: #get the moving average of daysMa=Get_ma (security_code,days)#If the sliding average exists (does not return Nan), then we already have enough data to initialize the EMA. if not(isNaN (MA)): G.emas[key]=Ma#the EMA of the previous period does not exist because it has just been initialized return(Float ("nan"), MA)Else: #Moving average data is less than days and has to return Nan value return(Float ("nan"), Float ("nan"))
" " ================================================================================ every day after closing ====================== =========================================================="# What to do after a daily close (not required in this strategy) def after_trading_end (context): return
Joinquant Policy code example