刘风老师,是这样的。因为我这是一个截面策略,叠加没有夜盘的品种,其实目的不是让没有夜盘的品种出信号,而是加载的品种之间需要在同一根BAR的截面上取CLOSE[1]计算一个全局变量指标,这个全局变量指标在对所有品种的信号计算是有作用的。在历史回测的时候,取非夜盘品种的CLOSE[1]会自动跳过非夜盘时间段往前回溯取值,而实盘时我想达到同样的效果。况且,即使对于有夜盘的品种来说,交易时间段也是不一样的。比如白银开盘到晚上2:30,螺纹钢开盘到晚上11点,那么白银在11点至2:30分之间,也会因为螺纹钢的交易时间已经结束,BarExistStatus==2,程序也会在11点后不再运行。所以,这个需求可以怎么实现呢?谢谢老师
回复:你既然是横截面策略,而且需要所有品种的close【1】来计算全局指标,那么到夜盘时间,你这个指标因为没有无夜盘品种的数据参与,那不就是计算无效了么?那还计算它干嘛呢?难道不是应该等到所有品种都有数据才计算吗?只要有一个品种返回交易时间无效,那就不应该计算
回复:刘风老师,可能问题并不在这里,因为我也试过把所有非夜盘品种都去掉,把白银黄金品种去掉,只留下交易时间段完全一样的品种,用上防信号闪烁那串数据对齐的代码,即使在白天交易时间段,也是会出现信号消失(表现为:监控器在实盘时不会显示不匹配,但一旦把策略单元停止并重启后,监控器即刻查出不匹配)。不匹配的原因有两种:要么是实盘委托了,事后查看图表没有信号。或者图表交易有信号,但实盘并不报单),看起来是很典型的信号闪烁或者信号消失问题。我把策略代码贴上来,代码不多,逻辑也不复杂。麻烦您帮我看一下行吗,因为问题困扰我很久了,谢谢!贴过来的代码在贴子里好像格式对不齐,见谅!Params Bool IsRollover(true);//是否后复权 Bool IsRolloverRealPrice(true);//是否映射真实价格 Bool IsAutoSwapPosition(true);//是否自动换仓 Numeric Fund(167000);//下单金额 Numeric N(25);//回溯周期 Numeric instNum(36);//品种数量 , Numeric WeekdaySet(2);//选择星期几交易 Numeric TimeSet(0.10);//选择哪个时间点交易 Numeric FEN(1);//用来取指标值排名第一和排名最后的参数Vars Global Array<Numeric> RR;//因子值 Global Array<Numeric> RS;//保存因子值的变量 //NumericArray atr; Numeric i; Numeric k; Numeric j; Global Array<Numeric> lots;//下单手数 Global Array<Numeric> myclose; Series<Numeric> RRup; Series<Numeric> RRdown; Integer status; Events //此处实现事件函数 //初始化事件函数,策略运行期间,首先运行且只有一次,应用在订阅数据等操作 OnInit() { Range[0:DataCount-1] { If(IsRollover) { AddDataFlag(Enum_Data_RolloverBackWard());//设置后复权 } If(IsRolloverRealPrice) { AddDataFlag(Enum_Data_RolloverRealPrice());//是否映射真实价格 } If(IsAutoSwapPosition) { AddDataFlag(Enum_Data_AutoSwapPosition());//设置自动换仓 } } SetGlobalVar2(\"Switch\", 0); //GetGlobalVar2(\"Switch\") } //在新bar的第一次执行之前调用一次,参数为新bar的图层数组 OnBarOpen(ArrayRef<Integer> indexs) { Numeric k; Numeric result=1; for k=0 to DataSourceSize-1 { result= result*data[k].BarExistStatus; } If(result<>1) Return; If(DATA[i].Rollover<>DATA[i].Rollover[1]) PlotBool(\"true\",True); //If(QuoteStatus() != 1) Return;//过滤集合竞价 Commentary(\"当前bar的时间\"+text(date+time)); //If(data!=data[1]and high==low) Return; //使用FOR循环,品种编号,全部使用索引 //#############################################数据获取计算部份################################## Commentary(\"当前bar的时间\"+text(date+time)); For i = 0 to instNum-1 { if(data[i].close[1]==data[i].close[2]&&data[i].close[2]==data[i].close[3]&&data[i].close[3]==data[i].close[4]) { RR[i]=10000000;//对于未上市的品种,将因子值赋予相对无限大,使其升序排序时不影响后面的交易 Commentary(\"data \"+text(i)+\" 出问题\"+text(date+time)); //print(\"data \"+text(i)+\" 出问题\"+text(date+time)); } else { Numeric mysummation; mysummation=summation(Abs(data[i].close[2]-data[i].close[3]),N); RR[i]=(data[i].close[1]-data[i].close[N])/mysummation;//ER因子 k=k+1; //print(\"status = \"+text(status)); } myclose[i]=data[i].close[1]/data[i].Rollover; lots[i]=(Fund+Portfolio_TotalProfit())/(myclose[i]*data[i].ContractUnit*data[i].BigPointValue*data[i].MarginRatio); data[i].Commentary(\"lots[i]=\"+text(lots[i])); } Commentary(\"k = \"+Text(k)); RS=RR;//用RS值来保存原始的因子值RR数组 Commentary(\"RS=\"+TextArray(RS)); //对因子值进行排序,排序后RR数组本身会发生改变 ArraySort(RR,True); //截取33%,66%分位数的因子值 j=MAX(1,FEN); RRup=RR[j-1];//得到排名前33% RRdown=RR[k-j];//得到排名后33% Commentary(\"RR=\"+TextArray(RR)); Commentary(\"j = \"+Text(j)); Commentary(\"RRup=\"+Text(RRup)); Commentary(\"RRdown=\"+Text(RRdown)); Commentary(\"Time=\"+Text(Time)); k =0; Commentary(\"RR1111=\"+TextArray(RR)); ////#############################################循环交易下单执行部份################################## Numeric Temp_RRup=RRup; Numeric Temp_RRdown=RRdown; For i=0 to instNum-1 { //做多排名第一的品种 If( RS[i]>=Temp_RRdown AND RS[i]!=10000000 AND data[i].MarketPosition!=1 AND Weekday==WeekdaySet and time==TimeSet) { print(\"当前bar1 \"+text(Time)); IF(data[i].MarketPosition==0) { DATA[i].Buy(Lots[i],data[i].Open); } Else IF(data[i].MarketPosition==-1) { DATA[i].BuyToCover(0,DATA[i].open); DATA[i].Buy(Lots[i],data[i].Open); } } //做空排名最后的品种 If( RS[i]<=Temp_RRup AND RS[i]!=10000000 AND data[i].MarketPosition!=-1 AND Weekday==WeekdaySet AND time==TimeSet) { print(\"当前bar2 \"+text(Time)); IF(data[i].MarketPosition==0) { DATA[i].SellShort(Lots[i],data[i].Open); } Else IF(data[i].MarketPosition==1) { DATA[i].Sell(0,DATA[i].open); DATA[i].SellShort(Lots[i],data[i].Open); } } //除了第一和最后,其它品种空仓 If(RS[i]>Temp_RRup AND RS[i]<Temp_RRdown AND DATA[i].MarketPosition==1 AND Weekday==WeekdaySet AND time==TimeSet) { print(\"当前bar3 =\"+text(Time)); DATA[i].Sell(0,DATA[i].open); } If(RS[i]==10000000 AND DATA[i].MarketPosition==1 AND Weekday==WeekdaySet AND time==TimeSet) { print(\"当前bar4 \"+text(Time)); DATA[i].Sell(0,DATA[i].open); } If (RS[i]>Temp_RRup AND RS[i]<Temp_RRdown AND DATA[i].MarketPosition==-1 AND Weekday==WeekdaySet AND time==TimeSet) { print(\"当前bar5 \"+text(Time)); DATA[i].BuyToCover(0,DATA[i].open); } If(RS[i]==10000000 AND DATA[i].MarketPosition==-1 AND Weekday==WeekdaySet AND time==TimeSet) { print(\"当前bar6 \"+text(Time)); DATA[i].BuyToCover(0,DATA[i].open); } } } //Bar更新事件函数,参数indexs表示变化的数据源图层ID数组 OnBar(ArrayRef<Integer> indexs) { } //下一个Bar开始前,重新执行当前bar最后一次,参数为当前bar的图层数组 OnBarClose(ArrayRef<Integer> indexs) { }
一般来说,图层信号闪烁用在跨周期上,不会有跨品种的交易时间不对齐的问题。你现在需要跨品种交易,那么不要把交易时间不对齐的品种放在一起。如果一定要放在一起,那么你自己要考虑清楚,既然是要放在一起,那么说明需要互相引用不同品种的数据,那么如果有夜盘的品种,需要无夜盘的品种数据,那么有夜盘的品种,夜盘时间为什么会出信号?无夜盘品种都没开盘,怎么会给出信号?对齐还有什么意义?那如果你不需要引用不同品种的数据,那又何必放在一个单元里做图层叠加呢?
回复:刘风老师,是这样的。因为我这是一个截面策略,叠加没有夜盘的品种,其实目的不是让没有夜盘的品种出信号,而是加载的品种之间需要在同一根BAR的截面上取CLOSE[1]计算一个全局变量指标,这个全局变量指标在对所有品种的信号计算是有作用的。在历史回测的时候,取非夜盘品种的CLOSE[1]会自动跳过非夜盘时间段往前回溯取值,而实盘时我想达到同样的效果。况且,即使对于有夜盘的品种来说,交易时间段也是不一样的。比如白银开盘到晚上2:30,螺纹钢开盘到晚上11点,那么白银在11点至2:30分之间,也会因为螺纹钢的交易时间已经结束,BarExistStatus==2,程序也会在11点后不再运行。所以,这个需求可以怎么实现呢?谢谢老师