A:国内市场规则本身是不支持部分证券资产(比如:股票,ETF等)的T+0交易的,在天软的回测框架中通过设置部分成员变量可以实现T+0回测,
目前实现T+0回测需满足以下条件:
1.组合类型选择数量类回测,即成员变量FGroupType=2;
2.数量类组合开仓数量类别选择固定成交量法,即成员变量FOpenVolType=1;
3.数量类组合平仓数量类别选择固定成交量法,即成员变量FCloseVolType=1;
4.设置可以日内平仓,即成员变量FNoT0 = 1;
5.不能设置不允许超卖,即成员变量FNoOverSold取默认值0。
实现示例
{
回测说明:以昨日涨停股为股池,回测期间持有5个股票,买入后若当天跌幅超过2%则卖出,并从股池中购入新股
注:1.回测期间已购买过的股票不在重复购买;
2.股池剔除st股
}
begt:=20251101t;
endt:=20251125t;
obj := createobject('HighFrequencyT0Trading');
//********************回测基本设置***************************//
//回测开始时间
obj.FBegT:=BegT;
//回测截止时间
obj.FEndT:=EndT;
//回测周期
obj.FCycle:=cy_1m();
// 回测初始资金
obj.FIniCash := 1000000;
//组合类型(数量类组合)
obj.FGroupType:=2;
//成交价类别(自定义价格)
obj.FPriceType:=-1;
//数量类组合开仓数量类别(此处采用固定成交量法)
obj.FOpenVolType:=1;
//数量类组合平仓数量类别(此处采用固定成交量法)
obj.FCloseVolType:=1;
// 可以日内平仓
obj.FNoT0 := 1;
//最大持有数量
obj.FMaxN := 5;
//记录已买过的的票
obj.Fdelstocks := array();
//回测
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),
);
Type HighFrequencyT0Trading=class(TSBackTesting)
FMaxN; //最大持有股票数
Fdelstocks; //已买过的的票不再购买
function GetTradeOrder(vEndT);override;
begin
oV := BackupSystemParameters2();
setsysparam(pn_cycle(),FCycle);
//当前时间
d := vEndT;
d0:=specall(LastTradeDay(d),array(pn_stock():"SH000001",pn_cycle():cy_day()));
echo datetimetostr(d);
cc := GetHoldData(); //获取当前持仓
cash := GetSurplusFund(); //获取剩余资金
ccstocks := sselect distinct(['代码']) from cc end; //获取持仓中的股票代码
Fdelstocks union2=ccstocks;
tjy := array();
n:=0;
if istable(ccstocks) then
ccnum := length(ccstocks)
else
ccnum := 0;
newccnum := ccnum;
if newccnum<FMaxN then //当前持仓股票个数小于最大持仓数
begin
stockArr:=sselect thisrow from GetAbkbyDate("A股",d0) where spec(StockIsZt(d0),thisrow) and not spec(IsST_3(d0),thisrow) end;
//判断开仓
for nI:=0 to length(StockArr)-1 do
begin
stockid := StockArr[nI];
setsysparam(pn_stock(),stockid);
setsysparam(pn_date(),d);
if not istradeday(d) then continue;
if not (stockid in Fdelstocks) then //已买过的的票不再购买
begin
tjy[n]['截止日'] := d;
tjy[n]['代码'] := stockid;
tjy[n]['名称'] := stockname(stockid);
tjy[n]['方向'] := 1;
tjy[n]['动作'] := 0;
tjy[n]['成交价']:= close();
tjy[n]['成交量'] := cash/(FMaxN-ccnum)/close();
n++;
newccnum++;
end
if newccnum>=FMaxN then break; //当持仓的证券个数大于最大持仓个数就终止开仓
end
end;
//平仓,对持仓循环判断是否达到平仓条件,当天涨幅小于2%平仓
for nJ:=0 to length(cc)-1 do
begin
stockid := cc[nJ]['代码'];
setsysparam(pn_stock(),stockid);
setsysparam(pn_date(),d);
zf:=stockzf6(dateof(d),d);
if zf<-2 then
begin
tjy[n]['截止日']:= d;
tjy[n]['代码'] := stockid;
tjy[n]['名称'] := stockname(stockid);
tjy[n]['方向'] := 1;
tjy[n]['动作'] := 1;
tjy[n]['成交价']:= close();
tjy[n]['成交量'] :=cc[nJ]["数量"];
n++;
end
end;
return tjy;
end
End;
回测结果:
部分T+0交易明细:
