经常会有客户咨询:
1. 为什么明明图表上有信号,但账户上却没有下单或者下了单持仓不对?
2. 为什么图表上只有一次开仓信号,却下单2次,也就是重复下单?
金字塔常见问题 问题13中有关这个情况做了解释.总结概括原因有两个方面,(1)网络问题;(2)公式本身有问题,如公式信号闪烁或带有未来函数.
下面我们将逐一为大家进行解读,告知大家遇到类似问题时问题排查的方法.
第一步,下单日志. ----查网络情况(这一步非常重要,请初学者用户务必打开该日志记录选项)
频繁的日志记录会影响到系统运行速度,从运行效率出发,下单日志默认情况是关闭的.打开的方法请参考 金字塔常见问题 问题24.
打开本地下单日志,我们会看到下单详细记录,以下示例为图表程序化交易"单子从本地触发到成交"的完整交易过程,一般分四步:(1)触发下单;(2)本地发出委托单;(3)收到委托成功的回报;(4)收到成交回报.
2013-03-11 09:59:00.218 【图表】IF03 运行完毕
2013-03-11 10:00:00.437 【图表】触发下单 SHELLSHORT 品种 IF03----(1)触发平空单
2013-03-11 10:00:00.437 【图表】分品种下单调整后,系数1
2013-03-11 10:00:00.437 【图表】模型下单 1
2013-03-11 10:00:00.437 【图表】下单系数调整后 手数:1
2013-03-11 10:00:00.437 【图表】实际持仓 -1
2013-03-11 10:00:00.437 【图表】直接下单
2013-03-11 10:00:00.437 【图表】触发下单 BUY 品种 IF03----(1)触发开多单
2013-03-11 10:00:00.437 【图表】分品种下单调整后,系数1
2013-03-11 10:00:00.437 【图表】模型下单 1
2013-03-11 10:00:00.437 【图表】下单系数调整后 手数:1
2013-03-11 10:00:00.437 【图表】直接下单
2013-03-11 10:00:00.437 【图表】IF03 运行完毕
2013-03-11 10:00:00.437 【下单】IF03 价0.000000 量1 买卖0 类型1 开平2 账户800*** Formula 1----(2)本地发出平空单
2013-03-11 10:00:00.437 【下单】IF03 价0.000000 量1 买卖0 类型1 开平0 账户800*** Formula 1----(2)本地发出开多单
2013-03-11 10:00:00.578 【回报】800034 : IF03 - 正在申报 1 价格:2579.40 平仓 买入----(3)平空委托回报,说明委托单已经下到交易柜台
2013-03-11 10:00:00.609 【回报】800034 : IF03 - 正在申报 1 价格:2579.40 开仓 买入
2013-03-11 10:00:00.718 【回报】800034 : IF03 全部成交 1 价格:2578.2 开 买----(4)平空成交回报,说明委托单已经成交
2013-03-11 10:00:00.718 【回报】800034 : IF03 全部成交 1 价格:2578.2 平 买
2013-03-11 10:01:00.437 【图表】IF03 运行完毕
2013-03-11 10:02:01.687 【图表】IF03 运行完毕
通过上述的日志记录,我们可以通过日志上大致能分析出几个方面的信息:
1.模型在出现问题的时刻是否还在工作着.如果已经停止工作,可能此时的网络已经断线.
2.模型在出现问题的时刻是否已经触发下单,如果已经触发下单,但是下单失败,日志上就会记录为什么会报单失败.
3.模型报单时提交的委托手数是否符合我们的设计需要的数量.
通过下单日志仍然无法解决, 1 图表上有信号,但是无实际下单指令出现; 2 重复下单; 这时要使用公式调试,通过公式模型中记录重要变量的方式来排查原因了.
第二步,记录日志-调试输出重要变量. ----查公式本身
金字塔的调试基本分3种方法 1、基于图表的公式调试;2、金字塔的公式调试器;3、通过记录日志方式调试.
详情请参考该帖http://www.weistock.com/bbs/dispbbs.asp?boardid=4&id=1246&page=1&star=1
前2种方式一般用在模型的开发阶段, 这里详细介绍第3种方式
金字塔一个非常重要的函数DEBUGFILE,可以将调试日志记录文件中,方便用户在编写复杂策略的过程中,逐步的完善策略的各个方面.
DEBUGFILE,该函数输出时会自动的加入时间,格式为:年月日时分秒.图表OR后台均可以使用该函数,来记录最后一根K线各个变量的值.
用法:DEBUGFILE(PATH,STR,NUM),PATH为用户的本地计算机路径,STR为用户指定输出的一个行文字,NUM为用户指定的一个监控数字.
例如:DEBUGFILE('D:\TEST.TXT','当前资产为%.2f',1234),将在程式化交易的监控部分输出到D:\TEST.TXT文件, "当前资产为1234.00","%.2f"为一个打印的控制符号,系统会将他替换为指定的一个数字输出,%.2f为显示两位小数,%.0f则表示不显示小数。
公式举例如下:
ma5:ma(close,2);
ma15:ma(close,5);
//5日均线上穿10日均线,开多
buycond:=CROSS(ma5,ma15);
if buycond then
begin
buy(holding=0,1,market);
end
//5日均线下破10日均线,平多
sellcond:=CROSS(ma15,ma5);
if sellcond then
begin
sell(holding>0,1,market);
end
以上简单示例,当buycond变量=1时发出开多指令,sellcond=1时发出平多指令,通过日志追踪开平仓条件等类似变量的盘中实时变化,最后就能找出实盘交易过程中我们的策略可能存在的逻辑问题. 下面将添加日志部分的代码如下:
ma5:ma(close,2);
ma15:ma(close,5);
//5日均线上穿10日均线,开多
buycond:=CROSS(ma5,ma15);
if islastbar then //@@@@@@@@@@@ 注意这里务必要增加ISLASTBAR条件判断只对最后周期有效,增加运行效率 @@@@@@@@@@@@@@
DEBUGFILE('D:\TEST.TXT',' buycond:%.0f',buycond);//输出开仓条件 @@@@注意:如果是序列工作模式,请使用 CONST 函数将buycond等序列变量转化为单值数据以提高字符串操作的工作效率。@@@@@@
if buycond then
begin
buy(holding=0,1,market);
if islastbar then
begin
DEBUGFILE('D:\TEST.TXT','holding:%.0f',holding);//输出HOLDING
end
end
//5日均线下破10日均线,平多
sellcond:=CROSS(ma15,ma5);
if islastbar then
DEBUGFILE('D:\TEST.TXT',' sellcond:%.0f',sellcond);//输出平仓条件
if sellcond then
begin
sell(holding>0,1,market);
if islastbar then
begin
DEBUGFILE('D:\TEST.TXT','holding:%.0f',holding);
end
end
红色标识,用于输出并记录您的开多条件OR平多条件,如果您发现开平仓信号与经验预期不一致,可结合下单日志和D:\TEST.TXT文件中的记录,看看是不是由于漏写了条件造成的. Islastbar函数用来控制只在最后一个周期才进行信号数据的输出,因为实盘交易过程中,金字塔也只使用最后一个周期的信号来实现自动交易.
实际使用过程当中Islastbar不是必须的,范例上只是让大家看清楚原理,因为DEBUGFILE函数本身就是最后一个周期才有效的函数. 我们的代码可能在调试日志输出的位置有多个变量输出,考虑到效率问题,强烈建议您在日志输出的位置加入Islastbar的控制符,可以大大的提升我们程序在逐K线模式下的运行速度.
此外做为日志记录的一种调试手段,我们一般会尽可能多的记录开平仓条件相关的变量,这样遇到问题时能够尽量快的通过日志来分析出问题的原因. 再进一步的完善日志输出的代码如下:
ma5:ma(close,2);
ma15:ma(close,5);
//5日均线上穿10日均线,开多
buycond:=CROSS(ma5,ma15);
if Islastbar then
begin
DEBUGFILE('D:\TEST.TXT',' buycondf'&numtostr(buycond,0)&' close:'&numtostr(close,2)&' ma5:'&numtostr(ma5,2)&' ma15:'&numtostr(ma15,2),0); //输出开仓条件
end
if buycond then
begin
buy(holding=0,1,market);
if islastbar then
DEBUGFILE('D:\TEST.TXT','holding:%.0f',holding);//输出HOLDING
end
//5日均线下破10日均线,平多
sellcond:=CROSS(ma15,ma5);
if islastbar then
DEBUGFILE('D:\TEST.TXT',' sellcond:%.0f',sellcond);//输出平仓条件
if sellcond then
begin
sell(holding>0,1,market);
if islastbar then
DEBUGFILE('D:\TEST.TXT','holding:%.0f',holding);
end
运行图表程序化以后,我们将得到如下的记录日志:
2013-03-09 02:00:05.484 buycondf:0 close:91.25 ma5:91.25 ma15:91.24
2013-03-09 02:00:05.500 sellcond:0
2013-03-09 02:00:06.156 buycondf:0 close:91.25 ma5:91.25 ma15:91.24
2013-03-09 02:00:06.156 sellcond:0
2013-03-09 02:00:09.156 buycondf:0 close:91.25 ma5:91.25 ma15:91.24
2013-03-09 02:00:09.156 sellcond:0
2013-03-09 02:00:10.140 buycondf:0 close:91.25 ma5:91.25 ma15:91.24
2013-03-09 02:00:10.140 sellcond:0
2013-03-09 02:00:10.640 buycondf:0 close:91.27 ma5:91.26 ma15:91.25
2013-03-09 02:00:10.640 sellcond:0
2013-03-09 02:00:11.640 buycondf:0 close:91.27 ma5:91.26 ma15:91.25
2013-03-09 02:00:11.640 sellcond:0
2013-03-09 02:00:12.640 buycondf:0 close:91.27 ma5:91.26 ma15:91.25
2013-03-09 02:00:12.640 sellcond:0
2013-03-09 02:00:13.640 buycondf:0 close:91.26 ma5:91.26 ma15:91.24
2013-03-09 02:00:13.640 sellcond:0
再遇到问题的时候,我们只要结合下单日志和我们的公式记录的重要变量日志,就可以知道到底问题出在哪里了.
学习了