策略:
交易所的tick数据每三秒一笔,因此可以将回测框架的周期设置为3秒,从而实现tick级别周期策略回测。这里给出的案例是使用3秒钟收盘价构造砖形图,使用砖形K线收盘价计算移动均线,移动均线金叉买入,死叉平仓。
砖形图:重新构建K线图,使每一个K线的长度相同。即价格每向上或向下位移一段固定距离,使用这段距离内的所有价格构成一条K线,砖形图相比于传统的K线图更平滑
具体实现:
注:下面案例中,更多成员变量的值及说明请查阅:FAQ:FAQ:
2023-09-25-应用专题-回测框架01:策略回测框架TSBackTesting(更新版)
Function RenkoBackTest();
Begin
Begt:=20191101T;
Endt:=20201130T;
obj:=createobject('MyTest');
//回测开始时间
obj.FBegT:=BegT;
//回测截止时间
obj.FEndT:=EndT;
//交易品种
obj.FStockID:='SZ000001';
//回测周期
obj.FCycle:=cy_3s();
//组合类别(数量类组合)
obj.FGroupType:=2;
//基准代码
obj.FIndexId:='SH000300';
//初始资金
obj.FIniCash:=50000;
//成交价类别(时点价格)
obj.FPriceType:=1;
//成交量取整模式
obj.FVolModType:=-1;
//是否分红再投资(不)
obj.FDividendType:=0;
//是否参与配股(不)
obj.FAllotmentType:=0;
//费用类别
obj.FFeeType:=1;
//砖形K线长度
obj.FRenkoLength:=0.3;
//长均线周期
obj.FLong:=20;
//长均线周期
obj.FShort:=10;
//砖形收盘价数组
obj.FRenkoCloseArr:=array();
//上一个砖形收盘价,初始值为0
obj.FLastRenkoClose:=0;
//回测
obj.BackTest();
//获取返回结果(返回结果可根据需要选择)
return array(
//---组合基础
"交易明细":obj.GetTradeData(BegT,EndT),
"资产配置":obj.GetAssetData(BegT,EndT),
"持仓明细":obj.GetHoldData(BegT,EndT),
//---组合盈亏、交易
"组合盈亏":obj.GetGainandLoss(BegT,EndT),
"交易汇总":obj.GetTradingAmount(BegT,EndT),
"组合盈亏(按证券)":obj.GetGainandLossBySecurity(BegT,EndT),
"交易汇总(按证券)":obj.GetTradingAmountBySecurity(BegT,EndT),
//---组合收益
"区间组合收益率": obj.GetPortfolioReturn(BegT,EndT),
"组合和基准收益率序列":obj.GetPortfolioReturn2(BegT,EndT),
"阶段收益":obj.GetTrailingReturn(EndT),
"滚动收益":obj.GetRollingReturn(BegT,EndT,cy_month()),
//----组合评价
"风险回报":obj.GetReturnandRisk(BegT,EndT),
"相对回报":obj.GetRelativePerformance(BegT,EndT),
);
End;
Type MyTest=class(TSBackTesting)
//增加属性
FStockID;
FRenkoLength;
FLong;
FShort;
FRenkoCloseArr;
FLastRenkoClose;
//重载下单函数,返回交易信息二维数组
Function GetTradeOrder(vEndT);override;
begin
//设置临时系统参数,取收盘价
with *,array(pn_stock():FStockID,pn_date():vEndT,pn_cycle():FCycle) do
begin
c:=close();
end
//价格位移距离大于等于
if abs(c-FLastRenkoClose)>=FRenkoLength then
begin
FRenkoCloseArr[length(FRenkoCloseArr)]:=c;
FLastRenkoClose:=c;
echo datetimetostr(vendt);
echo c;
end
else
return 0;
Len:=length(FRenkoCloseArr);
//收盘价数组长度不足以计算移动均线
if Len<FLong+1 then return 0;
//计算长短移动均线
longma0:=mean(FRenkoCloseArr[Len-FLong:]);
shortma0:=mean(FRenkoCloseArr[Len-FShort:]);
longma1:=mean(FRenkoCloseArr[Len-FLong-1:Len-2]);
shortma1:=mean(FRenkoCloseArr[Len-FShort-1:Len-2]);
tP:=GetHoldData(); //获取当前持仓
jymx:=array();
//ma10上穿ma20的时候买入
if shortma0>longma0 and shortma1<=longma1 and not istable(tp) then
begin
echo '买入',datetostr(vEndt);
jymx&=array(('截止日':vEndt,
'代码':FStockID,
'方向':1, //多单
'动作':0, //开仓
'成交量':1000,//单位 股
'费率(%)':0.1));
end
//ma10下穿ma20的时候平仓
else if shortma0<longma0 and istable(tp) then
begin
Opendate:=vselect ['截止日'] from tp where ['代码']=FStockID end;
if dateof(vendt)-dateof(Opendate)>=1 then
begin
echo '平仓',datetostr(vEndt);
jymx&=array(('截止日':vEndt,
'代码':FStockID,
'方向':1, //多单
'动作':1, //平仓
'成交量':1000,
'费率(%)':0.1));
end;
end
return jymx;
end;
End;
返回结果: