四目观天下

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划$ C8 u  ^! K0 g/ A* o0 Q
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。- X) [1 }0 X8 [4 \( [; L
这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。
2 h5 S! @, H0 |2 P. f/ H# s" O就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。
& w9 `0 J" L1 H准备奠基
, Z  h% k) t/ z% m. a7 X  O我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:% K# N$ u2 R8 k  Y& \
inline bool CheckFileIsBar(int &file, const string szFileName)
: l4 ?  g5 U2 b; ]# e{
. y+ _: @0 Q9 c7 H+ V! Mstring  szInfo = "";
( P: G' y8 _& {9 J0 xbool    bRet;
3 R+ |$ p" j9 U  {: ]for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);
) ~4 D; c% \% Y! Gif ((bRet = (szInfo == def_Header_Bar)) == false)3 r, p' T: U: h
{
8 U+ ]; M9 K2 c, v- f: i7 APrint("File ", szFileName, ".csv is not a file with bars.");
9 j8 H) r8 M+ j' F5 Z6 u; CFileClose(file);
& {$ a, M& k& \# `}
8 e5 @* W  P- Z6 f; N3 ]return bRet;, O- Z( M1 S: ~
}2 r4 Y! w2 O8 |& y
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:: N$ x# G7 M  l9 m$ C. _, k/ l
inline void FileReadBars(int &file, MqlRates &rate[])" O) n/ }/ z! C1 w' I
{  r/ N& h$ S) F- `' W) V) Z& \
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));
/ Z+ Z( j  q6 G  S" b. O) W! S2 Zrate[0].open = StringToDouble(FileReadString(file));3 M# |1 k( q  L" v- G  H* R
rate[0].high = StringToDouble(FileReadString(file));
( k- F. U: o; Trate[0].low = StringToDouble(FileReadString(file));
$ l4 F. v7 ^8 ?1 Y" E: H$ Jrate[0].close = StringToDouble(FileReadString(file));
$ u! o4 C" _$ V7 S9 r! U1 orate[0].tick_volume = StringToInteger(FileReadString(file));
: F* |/ F# ]0 x9 P3 N+ Z% \1 Z4 prate[0].real_volume = StringToInteger(FileReadString(file));0 T! x5 k* y0 L# e; y1 I/ u* P
rate[0].spread = (int) StringToInteger(FileReadString(file));
* j$ v+ S: i: [3 D}3 ?* F# ?) W, g' ~! k
它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:
; J( d) i6 }2 R3 w5 a9 F: |. G& Oinline bool OpenFileBars(int &file, const string szFileName)
% j( i! o9 @+ ]- O{2 B. t+ |# S9 U$ j0 }7 y) Z
if ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
4 g! W$ F( H- m3 I1 M3 g4 m{
- T% U/ w, C. v, X. sif (!CheckFileIsBar(file, szFileName))5 O+ N! k  ~' i
return false;
5 J7 A* g- L& |& greturn true;  ~/ E( D6 p5 G
}- q& Z: B$ O2 {$ s5 T: H$ @
Print("Falha ao acessar ", szFileName, ".csv de barras.");
: Y3 x# F! J1 ~* E- D9 s2 h/ \return false;
# T. e1 c' X7 u$ b. J3 X. h  y}+ j; l# A; d9 F7 m. P, g1 w9 o
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:
: I' Z  S7 I) f$ H. e; b% Xbool LoadPrevBars(const string szFileNameCSV)
& ^) \3 t& F( F% K9 |/ E{; B; U2 t: E' \7 h) ~+ A
int     file,
& k' c6 P, h& {) [0 z! K5 a$ P5 qiAdjust = 0;
, _5 ^! V6 g; R( W% Y( p) ^* tdatetime dt = 0;9 x1 z6 R# G* k+ D* K
MqlRates Rate[1];
. N( _% R4 V5 a8 Fif (OpenFileBars(file, szFileNameCSV))$ U3 U- b0 H" }
{: Y4 g2 B. P! g4 W( r( l9 H/ `* K
Print("Loading preview bars for Replay. Please wait....");
% v. K  g$ j8 q6 G' p' l; ewhile ((!FileIsEnding(file)) && (!_StopFlag))$ s' X6 i8 u% U. G, ]7 a
{! j; Z+ x( e+ z! E, |- T
FileReadBars(file, Rate);
; k( B, m" A- m3 m! u( `iAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);
7 n  w5 S3 Q5 v2 B  U9 |dt = (dt == 0 ? Rate[0].time : dt);9 d; J0 u" E1 s/ m4 |
CustomRatesUpdate(def_SymbolReplay, Rate, 1);0 _6 A" n; J7 v4 V( c, R. T
}
7 y% i9 W7 q1 k" jm_dtPrevLoading = Rate[0].time + iAdjust;
& D; A: T4 Z7 U7 o$ s( \# z5 {  f& DFileClose(file);* ^4 i- e3 [) L' Q! T. R
return (!_StopFlag);; h. \9 b7 H, H0 y, d
}, [6 B$ T' l1 j/ S
m_dtPrevLoading = 0;  V$ S6 S$ W5 D2 F1 w* u" O
return false;' T. r1 L( `4 e7 B; a9 ~7 Q" b
}
6 _- ^5 a6 E) |2 S这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:' o) [  r+ Z6 N$ T, l- A
#define def_STR_FilesBar        "[BARS]": Q' O) f. r# v; ]# T7 [( k
#define def_STR_FilesTicks      "[TICKS]"1 B9 T8 a, x, P
#define def_STR_TicksToBars     "[TICKS->BARS]"
' q7 L% ?3 r8 l#define def_STR_BarsToTicks     "[BARS->TICKS]"* }( D6 e+ R" s& b& R( K
这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-6 04:54 , Processed in 2.319307 second(s), 31 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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