-
实现目标
通过DolphinDB实现MA(Moving Average)移动平均线指标回测。
-
一、数据准备
采用火币网的btcusdt数据
# 构建数据 s_tmp = loadText("D:/Tools/DolphinDB_Projects/data/huobi_btcusdt.csv") stock = select symbol as sym, candle_begin_time as date, close from s_tmp
-
二、定义MA信号
# 定义MA信号,短期均线大于长期均线 def maSignal(x, shortHorizon, longHorizon){ signal = mavg(x, shortHorizon) > mavg(x, longHorizon) signal[0:min(x.size(), longHorizon - 1)] = NULL return signal }
-
三、交易策略
假设前一天的MA信号为prevSignal, 当天的MA信号为signal。
- 如果prevSignal=false, signal=true, 那么买入多头头寸(long position);
- 如果prevSignal=true, signal=false,那么卖出空头头寸(short position);
- 如果不符合上述两种情况,则保持与前一天相同的头寸;
-
四、不止损回测
# 计算每个股票每天的MA信号 t = select sym,date,close,maSignal(close, 50, 100) as signal from stock context by sym # 不止损回测函数 def backtest(t){ t2 = select sym,date,close,prev(close) as prevClose, signal, prev(signal) as prevSignal from t context by sym update t2 set position=iif(prevSignal==false and signal=true, 1, iif(prevSignal==true and signal==false, -1, int())).prev().ffill() context by sym return select sym,date,close,signal,position,position*(close - prevClose) as pnl from t2 where isValid(position) } # 实例化不止损回测 positions = backtest(t) # 统计策略详情函数 def calcPerformance(pnl){ result = dict(STRING, DOUBLE) result[`cumpnl] = pnl.sum() result[`avgpnl] = pnl.avg() result[`days] = pnl.size() result[`std] = pnl.std() result[`maxDrawdown] = (pnl.cumsum().cummax() - pnl.cumsum()).max() return result } # 计算盈亏并绘制盈亏走势图 dailyPnl = select sum(pnl) as pnl from positions group by date order by date result = calcPerformance(dailyPnl.pnl) // 返回一个字典 plot(dailyPnl.pnl.cumsum() as cumulativePnl, dailyPnl.date, "Cumulative Pnl of ALL Stocks without Stop Loss Control") # 分析每只股票的盈亏信息 select calcPerformance(pnl) as `cumpnl`avgpnl`days`std`maxDrawdown from positions group by sym
此方法是比较传统的回测,只是展示DolphinDB的速度快、代码简介,并不具有唯一性,唯一性还是其回放功能。