帮助文档中描述如下:onbaropen只在这根BAR的第一个TICK才会驱动代码运行一遍。
我在测试过程发现:onbaropen的触发时间在本BAR的TIME之前,请问此种情况合理吗?(感觉象是BAR[1]的ONBARCLOSE)此时BAR[1]的CLOSE形成了吗?(直接关系到均线、布林等技术指标的计算,从而影响至出入场)
onbaropen的设计原理是什么呢?我用数组记录每个TICK的TIME,在onbar域中设定open时间(即:第1个TICK)为:TickTime[1]<Time AND TickTime[0]>Time,又发生了重复触发的问题(原因大概是:TickTime有重复,难道一个TICK会接收两次吗?)。
我先确定一下我对基础机制的理解是否正确,根据情况再完善测试代码,请老师们解惑!!!
onbarclose-onbaropen-onbar
只有Onbar是正统的
你要是喜欢
全部在onbar自己控制
控制成
onbaropen-onbar-onbarclose
反正我就是这么干的
要么
加深、正确理解
要么
不喜欢TB给出来的机制
就自己重构
老师,请问您是如何实现在onbar中控制onbaropen的?可以分享思路吗(如有代码就更好了)?望不吝赐教,谢谢!!!
我在测试过程发现:onbaropen的触发时间在本BAR的TIME之前,请问此种情况合理吗?
请给出得到这个结论的证据
onbaropen的设计原理是什么呢?
用户需要,所以我们设计。常见需求举两个例子
第一个,有些指标在bar开盘的时候就已经确定了,放在onbar里计算就冗余了
第二个,有些状态变量可以放在onbaropen里做重置,避免放在onbar里被污染。
如果没有以上需求,无视就好了
//------------------------------------------------------------------------
// 简称: ZS39_2
// 名称: OPEN触发时间
// 类别: 公式应用
// 类型: 用户应用
// 输出: Void
//------------------------------------------------------------------------
Vars
Global Numeric StartTime;
Series<Numeric> BAR0(0); // BAR索引
Global BOOL TimeCond;//实时行情
Tick My_Tick;
Global Numeric TickTime2(0);//图层2/Tick时间
Global Numeric TickTime1(0);//图层1/Tick时间
Global Array<Integer> OrderId;//单号
Defs//自定义函数
Integer LogFile(StringRef str)//日志函数
{
IF (StrategyMode()==1)
FileAppend("D:\\"+FormulaName()+"\\"+DATA2.Symbol()+".txt","["+Text(SystemDateTime())+"] "+ str+"/"+StrategyModeName);
Return 0;
}
Events
OnInit()//策略执行前的初始化事件,只运行一次。/可以订阅数据,数据准备等操作。
{
SubscribeBar(Data0.Symbol,"5M",Data0.BeginDateTime);//图层1
SubscribeBar(relativesymbol,"1M",Data0.BeginDateTime);//图层2
}
OnReady()
{
StartTime=SystemDateTime; //返回值为YYYYMMDD.HHMMSS
LogFile("OnReady//"+SymbolName+"/开始时间="+TEXT(SystemDateTime()));
PrintClear;
}
OnBarOPEN(ArrayRef<Integer> indexs)
{
Range[1:1]
{
BAR0=CurrentBar();
TimeCond=IsTradingTime(Symbol,SystemDateTime)AND QuoteStatus==Enum_QuoteStatus_RealTime;
IF (!TimeCond) Return;
IF (GetTick(symbol,My_tick))
TickTime1=My_tick.dateTime;
Numeric Sc1=TimeDiffV2(Time,TickTime1);//时差1
LogFile("图层1/TickTime1="+Text(TickTime1,9)+"/Time1="+Text(Time,9)+"/BAR1="+TEXT(BAR0)+"/时差1="+Text(Sc1,9));
IF (Sc1<0)
LogFile("*******TickTime1提前/时差="+Text(Sc1,9));
}
Range[2:2]
{
BAR0=CurrentBar();
TimeCond=IsTradingTime(Symbol,SystemDateTime) AND QuoteStatus==Enum_QuoteStatus_RealTime;
IF (!TimeCond) Return;
IF (GetTick(symbol,My_tick))
TickTime2=My_tick.dateTime;
Numeric Sc2=TimeDiffV2(Time,TickTime2);//时差1
LogFile("图层2/TickTime2="+Text(TickTime2,9)+"/Time2="+Text(Time,9)+"/BAR2="+TEXT(BAR0)+"/时差2="+Text(Sc2,9));
IF (Sc2<0)
LogFile("TickTime2提前/时差="+Text(Sc2,9));
}
IF (1==2) A_Buy(symbol,1,Q_AskPrice,OrderId );//不发单
IF (1==2) A_Sell(symbol,1,Q_BidPrice,OrderId );//不发单
}
上面是测试代码,下面是日志的截图(部分)
暂时未能捕捉到触发时间明显提前的情况。但是仍有几个问题再请教
1、图层1(5分钟)为何多次触发?是否我在此域中对图层控制不够?如何控制其只在本图层的第一个TICK触发?
2、日志第7行,时差2=0有问题(SC2明明应该等于2)。TimeDiffV2应该返回毫秒级差值,此函数的准确性有问题吗?(函数本身设定的精度是多少?会四舍五入吗?)
3、日志第7行,触发时间点是在本BAR的TIME之前(尽管只提前了2毫秒), 是否可以推定上1个TICK就已产生了上1个BAR的CLOSE?
4、老师如需复现上述问题,请多试几个品种,盼解惑,谢谢!!!
驱动和执行是两码事。
你现在写的逻辑是,无论哪个图层驱动,都要执行图层1和图层2的代码
请问如何控制其只在本图层执行?
现在的测试代码,影响2、3两个疑问的成立吗?
建议看一下零基础教程里的说明。
行情驱动的事件域,参数indexes数组里存放的就是驱动的图层序号
这个教程里应该都是说过的
// 简称: ZS39_2
// 名称: OPEN触发时间
// 类别: 公式应用
// 类型: 用户应用
// 输出: Void
//------------------------------------------------------------------------
Vars
Global Numeric StartTime;
Series<Numeric> BAR0(0); // BAR索引
Global BOOL TimeCond;//实时行情
//Tick My_Tick1;
//Tick My_Tick2;
//Global Numeric TickTime(0);//图层2/Tick时间
//Global String Ticksymbol;//图层1/Tick时间
Global Array<Integer> OrderId;//单号
Defs//自定义函数
Integer LogFile(StringRef str)//日志函数
{
IF (StrategyMode()==1)
FileAppend("D:\\"+FormulaName()+"\\"+DATA2.Symbol()+".txt","["+Text(SystemDateTime())+"] "+ str+"/"+StrategyModeName);
Return 0;
}
Events
OnInit()//策略执行前的初始化事件,只运行一次。/可以订阅数据,数据准备等操作。
{
SubscribeBar(Data0.Symbol,"5M",Data0.BeginDateTime);//图层1
SubscribeBar(relativesymbol,"1M",Data0.BeginDateTime);//图层2
}
OnReady()
{
StartTime=SystemDateTime; //返回值为YYYYMMDD.HHMMSS
LogFile("Ready时间="+TEXT(SystemDateTime())+"/图层0="+SymbolName+"/图层1="+Data1.Symbol+"/图层2="+Data2.Symbol);
PrintClear;
}
OnBarOPEN(ArrayRef<Integer> indexs)
{
TimeCond=IsTradingTime(Symbol,SystemDateTime) AND QuoteStatus==Enum_QuoteStatus_RealTime;
IF (!TimeCond)
Return;
If(ArrayFind(indexs,1))
{
BAR0=CurrentBar();
Commentary("BAR0="+Text(BAR0));
Tick My_Tick1;
GetTick(DATA1.symbol,My_tick1);
Numeric TickTime1=My_tick1.dateTime;
String Ticksymbol1=My_tick1.symbol;
Numeric Diff1=TimeDiffV2(Time,TickTime1);//时差1
LogFile("图层1/"+ticksymbol1+"/Time="+Text(DATA1.Time,9)+"/TickTime="+Text(TickTime1,9)+"/时差="+Text(Diff1,9)+"/BAR="+TEXT(BAR0));
IF (Diff1<0)
LogFile("*******TickTime1提前/时差="+Text(Diff1,9));
}
//Range[2:2]
If(ArrayFind(indexs,2))
{
BAR0=CurrentBar();
Commentary("BAR0="+Text(BAR0));
Tick My_Tick2;
GetTick(DATA2.symbol,My_tick2);
Numeric TickTime2=My_tick2.dateTime;
String Ticksymbol2=My_tick2.symbol;
Numeric Diff2=TimeDiffV2(Time,TickTime2);//时差2
LogFile("图层2/"+ticksymbol2+"/Time="+Text(DATA2.Time,9)+"/TickTime="+Text(TickTime2,9)+"/时差="+Text(Diff2,9)+"/BAR="+TEXT(BAR0));
IF (Diff2<0)
LogFile("TickTime2提前/时差="+Text(Diff2,9));
}
IF (1==2) A_Buy(symbol,1,Q_AskPrice,OrderId );//不发单
IF (1==2) A_Sell(symbol,1,Q_BidPrice,OrderId );//不发单
}
上面是修改后的测试代码,下面是测试日志,相关问题仍然存在
2、日志第8行,时差=32760000有问题(明明应该等于-2)。TimeDiffV2应该返回毫秒级差值,此函数的准确性有问题吗?
3、日志第8行,触发时间点是在本BAR的TIME之前(尽管只提前了2毫秒), 是否可以推定上1个TICK就已产生了上1个BAR的CLOSE?感觉有的OnBarOPEN像是上根BAR的OnBarCLOSE
那你为什么不输出一下time呢?diff2不对,你输出了ticktime2,那输出一下time不就知道了么?
虽然你没有说明图层0是什么周期,但是我研究很久以后,推测你图层0是日线。日线的time,是0。而你2图层分钟线,090559,换成毫秒数,就是
自己算算是不是对上了吧
TIME已经输出了,且已核对:与图层相对应
况且TimeDiffV2是忽略日期差异的
感觉TimeDiffV2这个函数有点异常
你回看我昨天的日志,计算结果与今天差异太大,难道是函数本身发生变动了?
对测试代码修改了以下两行
Numeric TickTime1=My_tick1.dateTime-DATE;
Numeric TickTime2=My_tick2.dateTime-DATE;
测试结果如下,请看最后一行问题仍然存在