四目观天下

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划
: x: `9 d9 p+ Q# l4 [许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
; K$ T9 b! Q1 b, H. A  U0 N6 N这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。! ?) R; l, y1 ^) ?. Y% v
就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。
$ O' D( r2 I5 ~- X$ |准备奠基3 L! S2 ?" o6 t4 k
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
* R) z  p1 t# w% T) }, C$ N) U$ ^( Xinline bool CheckFileIsBar(int &file, const string szFileName)3 p% i0 A6 x/ j/ K+ M2 W" L& y
{/ E% D4 U8 h; Y$ m' N
string  szInfo = "";. r- _2 ?1 E" j$ S
bool    bRet;) b% E0 x2 [2 P% \$ k. e
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);5 @" T% E( R. L& U2 n9 S, a0 s' L
if ((bRet = (szInfo == def_Header_Bar)) == false), n  E' l7 [7 H+ a6 l5 m
{: K- @8 u8 p  O6 E
Print("File ", szFileName, ".csv is not a file with bars.");. p0 x- A9 ^, p7 W
FileClose(file);
% ]  _9 l' u0 s5 u1 [4 D6 B}
! _+ p1 H. Y+ mreturn bRet;
9 H& W& h' i. q6 |3 g}$ F. h% H3 X" a# q' i$ F! L/ C
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
" P8 w- @& E; F5 x  J" ]8 C( e8 d: Y7 Iinline void FileReadBars(int &file, MqlRates &rate[])
! q: L" Z# p: _7 {{! g; y! C) w4 X# l0 d+ l: D3 |6 b
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));' {) c. ^: B0 P$ {: Y+ G( `! L
rate[0].open = StringToDouble(FileReadString(file));
5 F/ |& `* Z7 x7 u; V8 d* Mrate[0].high = StringToDouble(FileReadString(file));2 b- Z; M) j. {& I, [: o  V
rate[0].low = StringToDouble(FileReadString(file));
( _3 y" s# Y! N  prate[0].close = StringToDouble(FileReadString(file));9 r4 Q+ q7 h1 q* C
rate[0].tick_volume = StringToInteger(FileReadString(file));
! w; a! V* M( p+ zrate[0].real_volume = StringToInteger(FileReadString(file));5 y! M$ {, I2 s/ Y* K( ?2 q. a
rate[0].spread = (int) StringToInteger(FileReadString(file));# j, x+ E- r$ Q( a8 m  h9 w
}! ^2 ~1 h; c4 g$ E  M
它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:
( ]$ D0 @8 c: a( j: W- rinline bool OpenFileBars(int &file, const string szFileName)% s0 k4 T! @( _( T7 i0 Z
{
' h5 J" q: B7 O8 y, H* T4 rif ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
! T/ P) m/ w$ ~{% O* w3 c) X7 r* G% n+ d6 W
if (!CheckFileIsBar(file, szFileName))
3 [' Q$ l2 ]. C6 C1 X9 e1 F; t  x2 {return false;
( p- L# N) H3 Qreturn true;+ e1 _4 w6 [/ o7 R( _
}
  D" |0 P3 W. u  _Print("Falha ao acessar ", szFileName, ".csv de barras.");
1 c- t! }9 N  c/ h" dreturn false;- z8 A# {8 D( V" W& ]
}; k  R# g0 M: A: U* N
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:7 X: `6 |& N8 [2 I9 u. ]- e
bool LoadPrevBars(const string szFileNameCSV)) r. x0 Q  N+ m' D5 n
{% L$ J  D/ U$ V* K! Y; _
int     file,) {7 @" X; R& b- d
iAdjust = 0;
+ N: F' p7 s" F& U  c0 bdatetime dt = 0;
1 o0 K9 G. ]7 Q6 _4 g5 SMqlRates Rate[1];: R" R' D3 [; Z" L
if (OpenFileBars(file, szFileNameCSV))+ c6 C+ @6 ], q' k6 c
{
1 [3 f3 b  b) l& i. O3 pPrint("Loading preview bars for Replay. Please wait....");
) A; l3 r: B' T  `$ Kwhile ((!FileIsEnding(file)) && (!_StopFlag))
% p$ K- w" C% P$ a3 C7 r{: q1 J9 h6 o5 T& C- l' G
FileReadBars(file, Rate);
/ D) |. g/ d: }; a3 YiAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);/ E5 p) ?9 R- g; Q
dt = (dt == 0 ? Rate[0].time : dt);  R4 K2 P( x% Q' u2 d5 Y) e( N
CustomRatesUpdate(def_SymbolReplay, Rate, 1);
# J3 K. R- D, M1 F7 E7 m}& N5 y/ x8 u2 M4 C8 h: i  S3 X9 }
m_dtPrevLoading = Rate[0].time + iAdjust;6 Q3 i) B2 c' k) e- S( I
FileClose(file);/ i, c. m1 R% J2 ~6 j8 G5 {
return (!_StopFlag);
: Y! S1 y3 _5 x4 Q0 R$ K0 P}" A; a9 M2 b2 _5 z
m_dtPrevLoading = 0;
. b( f" i1 e  @8 w  V1 {; T8 A) Mreturn false;
. s" t) [' W+ _! w; d}
( D- ?. _+ ?; S: ?. s6 S这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:
  y6 M" s  y! T$ _$ G0 r#define def_STR_FilesBar        "[BARS]"$ O8 `9 O; J2 M: k
#define def_STR_FilesTicks      "[TICKS]"
7 ?9 n( n9 |8 [  s6 M( i4 T9 B9 ~#define def_STR_TicksToBars     "[TICKS->BARS]"
6 b. ~7 J8 \  T8 |8 Y1 `/ }7 l#define def_STR_BarsToTicks     "[BARS->TICKS]"1 c, G0 P4 @$ m' @7 o- u; m
这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-5 16:46 , Processed in 3.371250 second(s), 31 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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