私募

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz

期货量化软件:赫兹量化中模拟器的诞生

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划& E4 {: q0 `1 J9 ]" W' u, ^
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。- V4 {+ q0 a- R1 Z$ W
这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。
# }. ~* }' q2 Q$ k就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。0 s( I& e  F( n' T
准备奠基6 i. q$ M/ V+ m. h
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
" f0 [8 l1 ~( d$ V# ~/ vinline bool CheckFileIsBar(int &file, const string szFileName)
7 s" Z5 n8 f! _7 G& {{4 J2 B4 Y2 e9 r/ A
string  szInfo = "";/ R7 T9 O4 Y3 l! F( r
bool    bRet;0 B0 \# |3 y+ V+ r% R- y
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);* X7 l6 V/ F9 x& Q. |: }& P0 H
if ((bRet = (szInfo == def_Header_Bar)) == false)
1 k9 x! _3 q1 `( `" H* L{
1 U  F" g+ o$ {5 u% @4 lPrint("File ", szFileName, ".csv is not a file with bars.");4 c9 o5 Q6 L  I! d# R8 `
FileClose(file);- B8 z7 r6 i0 D+ k
}: P- B' i& [) V; w; a! m
return bRet;
& ^* {5 u: C  B2 B}& b% C$ ?% H$ q6 o. J
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
8 T' }( p4 R" `( `inline void FileReadBars(int &file, MqlRates &rate[]). R0 A2 ^/ d3 [7 s. }
{+ e$ ]- \% M- F7 E0 S
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));$ ?4 t+ Z1 }; Q+ w2 {2 Q
rate[0].open = StringToDouble(FileReadString(file));7 |3 N: t7 F8 n( b2 g4 c, ?. W
rate[0].high = StringToDouble(FileReadString(file));
2 C: z: _* K" F- N1 ]rate[0].low = StringToDouble(FileReadString(file));1 {8 \& B6 @: `0 Y; ~
rate[0].close = StringToDouble(FileReadString(file));+ Z* m7 l0 K5 l# C' h  U8 J
rate[0].tick_volume = StringToInteger(FileReadString(file));; w+ Z/ s, r" W) A4 ]$ [+ H
rate[0].real_volume = StringToInteger(FileReadString(file));% y4 L$ O1 I+ Z
rate[0].spread = (int) StringToInteger(FileReadString(file));
4 `4 h% c- ^- t% Z" X}0 t; y7 h- i6 x
它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:
/ b3 X" S1 [" {) O& ]. X. oinline bool OpenFileBars(int &file, const string szFileName)
8 A/ \1 l5 \- N* `( u/ J{; k3 U$ D+ ^9 |+ a: X
if ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
' N* x; Z) e# A+ L$ Y{/ _9 T6 }  \4 `( t
if (!CheckFileIsBar(file, szFileName))
  s' U6 W# |( h5 ^. z- V0 lreturn false;
! _% P2 ^) p/ X8 y9 O3 @return true;
4 L' z; q! a# U3 u$ t. i}' {+ L% D6 f* j, f) C! @. ^
Print("Falha ao acessar ", szFileName, ".csv de barras.");
& O5 x& I! `! M0 vreturn false;: b' |5 |0 Y+ l7 }5 s. Q1 @) z% a
}
; V) \3 f! p0 E9 w8 e我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:& Y$ y* V' c+ z6 f% b
bool LoadPrevBars(const string szFileNameCSV): L8 v) F) p6 P- U- y# C* `  F
{& w3 a6 B6 F( n3 B
int     file,
% L! _9 c, k( ~, Z9 J% w: h- OiAdjust = 0;
0 G3 x# ?" ^  s. M- e* X0 z1 udatetime dt = 0;- u; L$ S8 y: {* W9 n9 {/ x* G
MqlRates Rate[1];) L) ?6 _' ]" `- t: c" l$ {0 ?4 _
if (OpenFileBars(file, szFileNameCSV))/ e9 o3 _. {* h' C* Q% v8 _2 E. S# |
{1 n( M/ e. ?! ^3 W6 C  s
Print("Loading preview bars for Replay. Please wait....");
+ W, b7 z' U- p& Fwhile ((!FileIsEnding(file)) && (!_StopFlag))
' S  J( }$ ?) y9 E5 k{. R) \" r, U8 L( P
FileReadBars(file, Rate);0 q  E3 Z# K# u3 n4 E  N' j
iAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);
* {; R# r" [3 e! q+ u5 K+ h4 Mdt = (dt == 0 ? Rate[0].time : dt);) R& P+ M8 A$ I3 R$ Q) b3 ^. u; @
CustomRatesUpdate(def_SymbolReplay, Rate, 1);3 b/ O1 x% R6 C' {& |4 C
}
( ?, y' Y/ ~. E6 ]m_dtPrevLoading = Rate[0].time + iAdjust;
; V$ Q4 H3 g& y1 oFileClose(file);8 O$ _0 n9 N) A$ d
return (!_StopFlag);3 \' K6 t: q+ i5 ~3 H. J
}
' ]% Y. c. i2 Z/ k+ }9 N* `3 W) ~m_dtPrevLoading = 0;
; P1 _  W7 @. @& Xreturn false;
' }0 D  j* A& N; C}5 W8 X& j6 \9 P: t4 y6 W
这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:- y) M! Z" p! L/ Y
#define def_STR_FilesBar        "[BARS]"# E. ~: I: R3 q, @5 O* O1 T  P
#define def_STR_FilesTicks      "[TICKS]"
$ j6 b1 j! p. W# ]) K- Z#define def_STR_TicksToBars     "[TICKS->BARS]"
: a1 c: ~, u; V+ B#define def_STR_BarsToTicks     "[BARS->TICKS]"! s0 ]/ }/ U6 D% o" W3 T3 y
这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Archiver| ( 桂ICP备12001440号-3 )|网站地图

GMT+8, 2025-6-14 20:11 , Processed in 0.390822 second(s), 31 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表