前阵子看监管那边又收紧了算法交易的报备要求,平台对EA运行日志的留存时间卡得越来越死,我才回头把自己那套日志模块翻出来重写了一遍。说实话,跑欧美这种点差稳定的品种时感觉不出问题,一旦切到黄金或者镑美这种波动大的,OnTick里随便一个除零或者数组越界,EA直接静默挂掉,账户还在那儿裸奔,连个报错都没有,这才是最要命的 😅
先说异常捕获这块,我踩过的坑最多。早期我图省事,整个OnTick用一个大try包起来,结果报错是抓到了,但根本不知道是哪个订单、哪个价位出的问题。后来改成按功能块拆:
对比一下方案:全局try优点是代码少、不漏异常,缺点是定位困难、性能开销集中;分块try优点是能精确到函数和参数、日志可读性强,缺点是要多写不少样板。我现在用的是分块方案,配合一个统一的LogError(函数名, 错误码, 上下文)封装,实盘排查效率明显高。
日志记录这块,我对比过三种做法。第一种直接Print到终端,优点是零成本,缺点是VPS上跑几天日志就被刷没了,回查基本靠猜。第二种用FileWrite写CSV,优点是能长期留存、方便拉回本地分析,缺点是频繁写盘在Tick密集时会有IO开销,黄金活跃时段尤其明显。我现在的折中是只在错误和关键状态变更时落盘,正常Tick不写,同时用FILE_READ|FILE_WRITE|FILE_CSV打开,文件名带上品种和日期,比如EURUSD_20241108.csv,方便按天归档。
具体落地我一般是这几步:
最后一个容易忽略的细节:日志里记录的价格和手数要用DoubleToString控制小数位,镑美我一般保留5位,黄金保留2位,不然CSV里全是浮点尾巴,后期用Python做归因分析时对不上。另外VPS时区要和经纪商服务器时间对齐,日志时间戳错位几小时,排查起来能把人逼疯。
你们平时EA报错是习惯看终端输出还是落盘分析?有没有遇到过日志文件被占用打不开的情况,评论区聊聊怎么处理的。
先说异常捕获这块,我踩过的坑最多。早期我图省事,整个OnTick用一个大try包起来,结果报错是抓到了,但根本不知道是哪个订单、哪个价位出的问题。后来改成按功能块拆:
- 下单模块单独try,捕获OrderSend返回码,重点盯134再报价和138报价超时
- 指标读取单独try,iCustom句柄返回INVALID_HANDLE必须立刻Print+ResetLastError
- 资金计算单独try,防止手数算出来是负数或者NaN
对比一下方案:全局try优点是代码少、不漏异常,缺点是定位困难、性能开销集中;分块try优点是能精确到函数和参数、日志可读性强,缺点是要多写不少样板。我现在用的是分块方案,配合一个统一的LogError(函数名, 错误码, 上下文)封装,实盘排查效率明显高。
日志记录这块,我对比过三种做法。第一种直接Print到终端,优点是零成本,缺点是VPS上跑几天日志就被刷没了,回查基本靠猜。第二种用FileWrite写CSV,优点是能长期留存、方便拉回本地分析,缺点是频繁写盘在Tick密集时会有IO开销,黄金活跃时段尤其明显。我现在的折中是只在错误和关键状态变更时落盘,正常Tick不写,同时用FILE_READ|FILE_WRITE|FILE_CSV打开,文件名带上品种和日期,比如EURUSD_20241108.csv,方便按天归档。
具体落地我一般是这几步:
- 初始化时FileOpen一次,句柄存全局,别每次错误都开关文件
- 日志字段固定为时间、函数名、错误码、订单号、价格、备注,字段顺序别乱改,不然后面解析脚本要重写
- OnDeinit里务必FileClose,VPS重启或EA被手动移除时句柄不释放,下次打开会失败
- 错误码用GetLastError()取完立刻清零,别让它污染下一次判断
最后一个容易忽略的细节:日志里记录的价格和手数要用DoubleToString控制小数位,镑美我一般保留5位,黄金保留2位,不然CSV里全是浮点尾巴,后期用Python做归因分析时对不上。另外VPS时区要和经纪商服务器时间对齐,日志时间戳错位几小时,排查起来能把人逼疯。
你们平时EA报错是习惯看终端输出还是落盘分析?有没有遇到过日志文件被占用打不开的情况,评论区聊聊怎么处理的。
