私募网

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划' C5 ~9 a0 f3 h; I. ^, O- M' u( y
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
3 N" A& E$ k3 J* u/ H5 y这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。* P- A( X  R% i
就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。$ D8 I; d' g+ O0 j! h3 T7 W
准备奠基# t" {( x5 {, C" {6 M
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:& u& S9 r" c+ f# W, j% l* H# S* e
inline bool CheckFileIsBar(int &file, const string szFileName)
7 T2 s4 w7 {! a& g{
$ p" w( Y) y3 A& g0 B; R0 Ustring  szInfo = "";
/ T- e& m* Q* u4 t/ l6 @* H' Dbool    bRet;4 x" s8 H9 x- @7 z( v4 B- n2 p) J
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);  q, e+ X0 a% g% Q- L5 Z
if ((bRet = (szInfo == def_Header_Bar)) == false)
& g9 \+ h9 O4 y; \{0 c/ T0 G. T' b! W5 c4 x! D1 j
Print("File ", szFileName, ".csv is not a file with bars.");
& f* q0 j" o+ i2 TFileClose(file);
3 B5 f; q% b) l/ s' r9 |* l}1 |3 n) l- b/ P) Z
return bRet;+ f; a- T) I9 A! j& M
}
$ e, N: v$ a3 ?2 F* W6 K/ T此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:0 [3 u9 j' X) {) t3 r
inline void FileReadBars(int &file, MqlRates &rate[])
6 j7 ]- M2 }, ~0 |% n% I5 H* J5 l{
# s# K6 r7 A2 K# ~- jrate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));
! }. a# h/ a. n; }; Crate[0].open = StringToDouble(FileReadString(file));
/ E) U- C# i5 O3 urate[0].high = StringToDouble(FileReadString(file));
) t) r. Z8 z: j, B! erate[0].low = StringToDouble(FileReadString(file));
* f; J, v( t  G- x5 P6 lrate[0].close = StringToDouble(FileReadString(file));* g& z! _9 z' T5 M, Z% W' e6 t$ M
rate[0].tick_volume = StringToInteger(FileReadString(file));; W4 H$ t/ w3 Y" m  J8 |
rate[0].real_volume = StringToInteger(FileReadString(file));; ]# Z1 s* O9 a9 \% l( Z/ }. X
rate[0].spread = (int) StringToInteger(FileReadString(file));  j5 I4 j) F5 a' ~: C
}1 A+ Q' J/ v# \- E
它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:6 I. E% A/ S, |9 J/ Y% n
inline bool OpenFileBars(int &file, const string szFileName)
6 B4 ~, c' }2 L! P. _1 C{" n9 z8 e" `0 W7 s6 H& d, u
if ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
4 e- ~9 c% j3 q% @9 }& }* G2 h6 X* i{4 \: C$ ]9 O( ^+ M) }" C, c
if (!CheckFileIsBar(file, szFileName)). U" a" H+ q. ?+ r* n* f
return false;% v$ L1 B7 s6 y& O- ]% J: `
return true;
  {: M1 {( u" u) V}5 ^% J  J2 W  A2 ^# p0 @
Print("Falha ao acessar ", szFileName, ".csv de barras.");
  [3 t$ F6 q1 C: @5 @+ B( ^( ireturn false;2 ]' r3 G% Y" y( Y  C7 z( ?' @
}% f; P. g" _2 _9 I9 I' R2 _* h1 Q. l
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:
: P+ Z$ H6 k: C& g/ r2 k. ?- M" s. ybool LoadPrevBars(const string szFileNameCSV)9 a$ H1 F4 y. w  s) r
{+ w5 e' S. {4 v+ k1 x+ V' z# c0 g7 b3 `
int     file,
9 U1 _3 L0 a! D- t0 d3 O: q; DiAdjust = 0;
% S7 N* m8 P  Q. |# j/ W4 Tdatetime dt = 0;
# m+ _, {4 R, GMqlRates Rate[1];
. W5 O4 g( c$ _! E2 m0 {7 E0 sif (OpenFileBars(file, szFileNameCSV))
7 V! @& Y& s8 |% H6 P$ p8 V$ S3 N{
  h& Y5 c; A' l5 b, RPrint("Loading preview bars for Replay. Please wait....");
4 G3 T+ {' D' N! l  u# twhile ((!FileIsEnding(file)) && (!_StopFlag))- j# W* \! z$ ~5 Q1 N5 v. y
{+ j# ]; l  D. `/ V* ?- c
FileReadBars(file, Rate);
6 h, ~5 Q0 Z0 d$ b& K3 z* qiAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);
' T0 `, c5 c# L2 Cdt = (dt == 0 ? Rate[0].time : dt);
, B; p: W/ U* H" S" a) uCustomRatesUpdate(def_SymbolReplay, Rate, 1);
# B. ]5 k6 V2 `) n9 D/ r}9 J9 Q% n, R) v/ R+ h- H
m_dtPrevLoading = Rate[0].time + iAdjust;3 d, }+ Z1 i+ `; i
FileClose(file);( T( ^& ~4 v3 d
return (!_StopFlag);+ M" y' F( U2 l" L: z5 i. x
}
" }9 V- K+ L( t; u* Am_dtPrevLoading = 0;
: b; z: o& |* _6 v( Treturn false;8 L/ n  ?1 x/ P" \* ?1 }, p
}
/ W2 `/ Y+ _# e3 U' P3 h这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:
) J5 ~2 I8 W% K7 D, B- Y2 m! T. S#define def_STR_FilesBar        "[BARS]"
( [' S) A6 u9 F#define def_STR_FilesTicks      "[TICKS]"8 M' Q& y; t+ }2 q6 O9 K9 B
#define def_STR_TicksToBars     "[TICKS->BARS]"$ K& e' Q9 V; [) n* z6 F+ P' G  j
#define def_STR_BarsToTicks     "[BARS->TICKS]"
8 @, w- _& r% ?6 y  H这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-3-30 00:35 , Processed in 3.970335 second(s), 32 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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