以文本方式查看主题 - 金字塔客服中心 - 专业程序化交易软件提供商 (http://weistock.com/bbs/index.asp) -- 高级功能研发区 (http://weistock.com/bbs/list.asp?boardid=5) ---- 软件调用策略速度太慢问题 (http://weistock.com/bbs/dispbbs.asp?boardid=5&id=172054) |
-- 作者:solegoose -- 发布时间:2019/9/16 14:21:16 -- 软件调用策略速度太慢问题 我现在想在5秒线上交易,发现速度很慢,我就测试一下,赶紧软件在调用策略的时候速度太慢,不知道有没有什么办法解决,或者是用专业版能否解决这个问题呢? 我先弄一个策略,里面只有这么一句: ret := "test@test"(); 就是调用test.dll函数中的test函数,其它任何语句都没有了,也不送入自定义的参数。 然后在test函数中,我用QueryPerformanceCount函数进行读取CPU的时钟周期,在我的机器上,QueryPerformanceFrequency函数返回的结果是10000000,也就是说,QueryPerformanceCount返回结果的单位是100纳秒,结果发现test函数两次调用之间的间隔可达好几百,多的可以到达1000多,这样算起来,两次函数调用的间隔居然能到达好几十微秒,如果有10000根K线,那么这个时间就需要几百毫秒,而此时还没有任何的策略计算。 对于5秒线来说,1天的K线数就达到5000以上,例如原油,金银。 |
-- 作者:无为剑 -- 发布时间:2019/9/16 16:43:35 -- 1,不清楚你是否是以序列模式还是逐K线模式调用的DLL,因为如果是逐K线模式的,你的DLL也必须设计成逐K的对应模式 2,你记录的CPU时钟周期是用什么记录的,如果是TXT文本等方式记录的,本身记录这些也需要时间的
|
-- 作者:solegoose -- 发布时间:2019/9/16 18:58:40 -- 是逐K线模式的,我的代码如下。 __declspec(dllexport) int WINAPI RUNMODE() { //本DLL运行序列模式,如果运行逐K线模式将此函数返回1,此时每执行一个K线都是调用本接口一次。 return 1; } 策略函数中的代码如下:
if (p->m_dwBarpos == 0)
{
QueryPerformanceCounter(&start_tick);
fprintf(fp, "%lld\\n", start_tick.QuadPart);
}
p->m_pResultBuf[0] = 0;
if (p->m_dwBarpos == p->m_nNumData - 1)
{
LARGE_INTEGER
freq;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&end_tick);
fprintf(fp, "%lld, %lld\\n", end_tick.QuadPart,
(end_tick.QuadPart - start_tick.QuadPart) * 1000 / freq.QuadPart);
}
return 0; 只在第一根K线和最后一根K线做日志,故不是写文件引起的速度慢。 输出的结果是: 50594583544 50602855894, 827 总共耗时827ms,这样的耗时算得上很吓人吧。K线数目31338根。平均每根K线耗时20多微秒。这个情况你们自己可以测试的。 |
-- 作者:无为剑 -- 发布时间:2019/9/16 21:44:46 -- 我前面解释过了,你用fprintf打印日志时也是需要时间的 |
-- 作者:solegoose -- 发布时间:2019/9/17 20:19:59 -- 我晕,你看代码了吗,我只在最后一根K线的时候调用了fprintf,不是每根K线都调用的。 |
-- 作者:solegoose -- 发布时间:2019/9/18 14:37:46 -- 版主能解答一下吗,整个过程中我只调用了2次fprintf,硬盘是固态的,不可能需要很多时间的。 |
-- 作者:张志远 -- 发布时间:2019/10/9 14:41:41 -- 忘了版主吧,我写python养你 |
-- 作者:无为剑 -- 发布时间:2019/10/14 14:35:12 -- 经过我们内部测试,测试程序如下: //计算收盘价的均价,一个常数参数,表示计算周期 //调用方法: // "STOCKFUNC@MYMACLOSE"(5) DWORD dwStart; FILE *fp; __declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData) { if ( pData->m_pfParam1 && //参数1有效 pData->m_nParam1Start<0 && //参数1为常数 pData->m_pfParam2==NULL ) //仅有一个参数 { if (pData->m_dwBarpos == 0) { fp = fopen( "d:\\\\mytest.txt", "w" ); dwStart = ::GetTickCount(); fprintf(fp, "%lld\\n", dwStart); } pData->m_pResultBuf[0] = 0; if (pData->m_dwBarpos == pData->m_nNumData - 1) { DWORD dwEnd = ::GetTickCount(); fprintf(fp, "%lld, %lld\\n", dwEnd, (dwEnd - dwStart)); fclose( fp ); } } return -1; } 由于每次测试的结果只都有所不同,大致取中位数如下: 当K线数量为 34000根时 406ms 当为4000根时 47ms, 其中5ms为fprintf写盘时间,测试机器 I7 8750 测试结果大致为你前面的一半,并未达到800ms以上,建议你测试时关闭所有图表的公式,逐k运行时其他的pel公式也会影响本pel公式运行。 有关你提到的效率问题,做如下回答: 逐K线模式运行时,每根K线都会去对PEL运行引擎做计算调用操作,406ms的计算时间,其中有350ms均消耗在此,其他的50ms是计算前的初始化和计算后的数据处理消耗。 3万4千根K线的调用DLL裸计算速度为400ms这个效率对于PEL来说后面也没什么太多空间了,运行卡顿主要消耗点应该还是在你的DLL策略本身,建议您对你的DLL做效率优化。如果你的策略对于这3万4千根k350ms的计算消耗非常在意,你可以考虑直接使用我们金字塔提供的C++开发接口,直接调用我们提供的数据API和下单API来直接交易。 参考 使用金字塔C++ API开发策略的优势 |
-- 作者:solegoose -- 发布时间:2019/10/14 14:59:24 -- 我测试的机器cpu较差,你们测试的情况和我测试的结果一样。 我不知道你说的PEL是不是你们金字塔那个语言的引擎,好像为每一根k线调用一次引擎不合理。毕竟这里不需要调用语言中的任何函数,不需要任何指标。 我们dll内策略的优化是另外一回事,因为我们的策略只需要计算最后一根K线,前面所有K线的中间结果都有缓冲。当然以前我们的策略依赖PEL中的均线箱体等,这部分可能速度较慢。 |
-- 作者:FexTel -- 发布时间:2019/10/14 15:03:32 -- 你是通过PEL去调取DLL执行的,所以会调用脚本语言引擎进行处理 |