私募

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划
) ^! X& \. P* C, Q1 \; s$ v许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
1 S- R( B8 ?2 l3 N$ @  R2 w这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。
* D- [2 ?1 m  T" q. V$ M1 E就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。' |) z+ z# N, U
准备奠基; N$ L( t6 C* K! X+ Q) C
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
" U- ?/ ~9 X& Q* H) Ninline bool CheckFileIsBar(int &file, const string szFileName)$ E; q  B. ]* G" R& `- R1 D. n
{: E+ _5 n) a+ x; Y
string  szInfo = "";0 g& r( E$ F( `, Y1 v8 Z
bool    bRet;8 ~5 {8 N$ g9 g6 K
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);
4 M$ E6 P5 m( B& i/ U, ?if ((bRet = (szInfo == def_Header_Bar)) == false)5 Y- w  S! G' v- s7 |# C
{
9 X+ n3 V: |& t* m# y  o) o& S4 GPrint("File ", szFileName, ".csv is not a file with bars.");9 G: K: M0 Q9 u2 L3 m
FileClose(file);7 }1 U/ M: G( Z- @# E
}# r  Q) D; m6 n4 o4 `
return bRet;  u: f1 M( G  v( D
}# x% n) ]) Z( m# M1 p7 W% y
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
- N" T/ ^7 c) y, O( h- `inline void FileReadBars(int &file, MqlRates &rate[])7 V' E1 z. `1 ^+ w" m
{
- e% {2 h7 k  ]  urate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));6 i4 U; i% J+ z0 Y8 |4 \
rate[0].open = StringToDouble(FileReadString(file));
# @; h+ p' [2 n5 @/ d- v( |$ Srate[0].high = StringToDouble(FileReadString(file));
2 n, f4 Y3 c, c" S0 G3 b9 K0 {rate[0].low = StringToDouble(FileReadString(file));& A$ k, _1 o' Z2 W' M
rate[0].close = StringToDouble(FileReadString(file));) @( z' {8 S" P6 M: N
rate[0].tick_volume = StringToInteger(FileReadString(file));5 C* V8 t1 N1 ^) E8 l0 n
rate[0].real_volume = StringToInteger(FileReadString(file));" e4 Y; B  d5 M  _: C3 h7 ?
rate[0].spread = (int) StringToInteger(FileReadString(file));* o3 M. a7 ~/ r5 u
}
5 `! Q5 r2 R7 x2 _$ I它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:
5 J4 k* L8 T" r: W- I1 linline bool OpenFileBars(int &file, const string szFileName)' j. |1 t$ m# k, M! L
{
- W4 |* N! \! `) gif ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
, O0 X! o& E! o. j{
6 w9 X7 f: I8 W% S2 l% rif (!CheckFileIsBar(file, szFileName))7 {" y/ q% A, r9 d* N
return false;* S- ^0 `$ T+ F3 u8 K) }0 \
return true;  S- P& m6 y) M$ p. z6 N
}
, Q' b$ X  q, e! p/ S9 [; u! A  UPrint("Falha ao acessar ", szFileName, ".csv de barras.");
5 Q# ?9 C$ {0 s: s2 i$ b+ breturn false;5 x3 O5 v# D- b3 C/ \8 a" g
}% `0 ]8 J. g1 k) P; V( t9 ]
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:7 D1 @( Q1 q9 l% [: q
bool LoadPrevBars(const string szFileNameCSV)
. G2 L; E7 l3 l# ^{. o6 M8 J$ g) U- g# f7 W
int     file,
4 r/ ~: U* t* liAdjust = 0;
' o0 \3 X4 N  k( i! Cdatetime dt = 0;
1 K! }: [% L, U4 tMqlRates Rate[1];
* k- Y( S1 b1 M% u2 y" j; Wif (OpenFileBars(file, szFileNameCSV))
8 V1 A0 i( Y; g* ~% G{3 O% k6 W' o' X4 `8 h" q, a# E
Print("Loading preview bars for Replay. Please wait....");
* }$ z9 y9 Z, N4 x8 Jwhile ((!FileIsEnding(file)) && (!_StopFlag))
4 ~7 _0 {/ o" z1 L{
7 A( [; Q3 \  I, r- f' n* Z( VFileReadBars(file, Rate);4 }& ?4 X$ U1 f8 r8 r& t' o+ e& G
iAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);1 W3 X6 ~' d8 e& \' H- f2 y
dt = (dt == 0 ? Rate[0].time : dt);7 U# X8 o" e+ t* a( z2 v$ `5 q
CustomRatesUpdate(def_SymbolReplay, Rate, 1);
  W8 g6 Q, M) H9 W; Y: f, V7 k}6 a# F: ?$ g8 M: T" ?
m_dtPrevLoading = Rate[0].time + iAdjust;6 m" s7 P6 L+ _$ k; E2 m, G
FileClose(file);
* s' U$ G& N  W8 F' u: wreturn (!_StopFlag);/ A- O$ Z7 d- a9 u8 R
}. X& g4 f' B' T& i7 X2 x
m_dtPrevLoading = 0;
9 m- z% C% _* q) O5 preturn false;
1 T5 q' j" U: U! z7 d}5 J& I1 z7 `* m
这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:4 ?6 z4 }  R' {+ A
#define def_STR_FilesBar        "[BARS]"
  O+ [0 `. }4 I- O3 R! P#define def_STR_FilesTicks      "[TICKS]"+ m5 T% J" p: O$ ^. w! y: }1 h
#define def_STR_TicksToBars     "[TICKS->BARS]"* i" x+ V% R1 [' b* k
#define def_STR_BarsToTicks     "[BARS->TICKS]"
8 ]% N/ m& U9 B' H- ~" C! G这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-10-28 14:45 , Processed in 1.307481 second(s), 32 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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