私募

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划  q- C5 k+ F7 [# r
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
* v4 `$ z, r4 Q9 v/ T这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。
" \0 E! A( A9 _3 c& r就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。
4 [1 j: B. ]% }" H( o5 c& E准备奠基% t, t: s" _- v0 p9 e- o, q
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
7 ^* G/ |  g0 s+ f, |inline bool CheckFileIsBar(int &file, const string szFileName)# m/ u! ?* ~% v0 G, Y
{
$ W) N3 a# H" R0 \& T, {) zstring  szInfo = "";1 |( `+ d3 u% V% {+ }) E
bool    bRet;+ N5 P* k; s  H* n1 b5 k
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);
/ T; r: `' v1 E% u% ?) \if ((bRet = (szInfo == def_Header_Bar)) == false)3 F. _2 K2 ]- s/ ~" \
{+ k4 q1 L5 `- G. E) Y+ T  q& C
Print("File ", szFileName, ".csv is not a file with bars.");
/ ~# g6 q& L7 x$ cFileClose(file);
1 ^- Q+ s9 N, F}
. N* _3 S2 R$ `# h) {; wreturn bRet;
5 a/ g% n7 J. s: x3 J  e}: N) |! `5 L. Q% y; W$ o
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
, q0 ]- o9 j+ s. I8 ninline void FileReadBars(int &file, MqlRates &rate[])
8 M8 P3 r9 t7 O{/ ?) o: y# }  k/ v9 R9 k1 r* [
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));
- i6 e  }0 |/ a% `' e6 Crate[0].open = StringToDouble(FileReadString(file));) K5 {. K& Z( B3 ~& f+ K2 ~7 u) O
rate[0].high = StringToDouble(FileReadString(file));( s. {+ E# v9 B9 M. U( q% H3 c' w
rate[0].low = StringToDouble(FileReadString(file));  _! k# @5 d' {' ~
rate[0].close = StringToDouble(FileReadString(file));
$ x) y' M9 b1 D0 p& Mrate[0].tick_volume = StringToInteger(FileReadString(file));, [$ @, f  N2 V* \
rate[0].real_volume = StringToInteger(FileReadString(file));. B; Z, P7 G7 c9 B6 O5 @
rate[0].spread = (int) StringToInteger(FileReadString(file));
1 |7 R! I; I4 \9 y* f}# x6 }9 G+ y9 X# q' [
它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:  l8 f9 R* ~) M: n8 `
inline bool OpenFileBars(int &file, const string szFileName)
1 z9 I$ U) b( h2 G9 H! x{
3 ?; a- F& k: w! i" G7 O8 Uif ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
9 a2 q' c+ k' P( |' y{* |0 ?8 \& ^8 g( |
if (!CheckFileIsBar(file, szFileName))
1 ~! h: Q6 [5 e2 M! h7 A* Greturn false;& d" G6 N6 H1 A+ n, B
return true;  y; u' j, U6 M  |/ N/ F
}6 C% t3 v9 [- k8 d6 H
Print("Falha ao acessar ", szFileName, ".csv de barras.");$ c* a9 r( `) N/ p7 b, _' {% r
return false;
% L, A4 q( |* q2 s" h. a}- u7 I& \: Z" a6 @8 O5 u
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:& {2 S( s' r7 _: g
bool LoadPrevBars(const string szFileNameCSV)
: B! f! R7 I- l5 M. m  E0 T{
9 X! y" k" f4 o. n/ cint     file,- W& b2 s, L" {, b! F7 k
iAdjust = 0;0 q8 P7 J" _; C3 _6 D# \
datetime dt = 0;5 P% ~8 e# {% ^/ i4 f; @
MqlRates Rate[1];
+ [% J$ J, a) r# V4 aif (OpenFileBars(file, szFileNameCSV))
) W0 U* p; F* @{
& X$ c4 O' N0 d! N2 Y% E+ ]Print("Loading preview bars for Replay. Please wait....");) m+ h+ m  P# @- B) u
while ((!FileIsEnding(file)) && (!_StopFlag))& J4 s3 M9 T$ r% v5 O1 P, ^+ s: s" F4 B
{4 c6 l0 N3 v% Z" ~5 R  ~1 Y
FileReadBars(file, Rate);
1 G6 U1 e# y' B6 H! ?  uiAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);& o% H3 A! Y# Z3 R3 B" @
dt = (dt == 0 ? Rate[0].time : dt);- m5 L! J5 G5 _- Z9 s8 [) Q( ?3 T, Z
CustomRatesUpdate(def_SymbolReplay, Rate, 1);6 X4 g' @8 O4 J+ Y* }# z  H
}
6 w& U) i+ f4 u5 s8 y5 Tm_dtPrevLoading = Rate[0].time + iAdjust;5 K1 I) u8 z% T* r8 |+ L
FileClose(file);& J- P" L+ L, h% x* c+ H' W& d
return (!_StopFlag);( Q, ^' V9 ?: X1 W' G. w
}% D) u3 t7 ?5 e; W5 s9 b
m_dtPrevLoading = 0;2 y' f# R4 N* R1 Z) M
return false;
/ b+ Y6 y8 c' @( v1 ?" d! o}, L8 c2 m/ C) T5 a: ?
这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:
7 N7 Z  o) f3 q#define def_STR_FilesBar        "[BARS]"
$ i( T% _4 l/ e& ]/ ?8 a) [. |! z#define def_STR_FilesTicks      "[TICKS]"# O+ @! ~& R. A
#define def_STR_TicksToBars     "[TICKS->BARS]"
5 q1 Y) C& ?' K* Q5 ?- O; W#define def_STR_BarsToTicks     "[BARS->TICKS]"( v. u) X% Y+ i7 d2 j4 D
这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-29 21:55 , Processed in 3.625191 second(s), 32 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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