私募

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划0 ?8 D# O/ f5 f: M# {: h
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。; O# Y9 k& l9 s- S$ u
这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。' `- M) [1 y* Y9 p2 e
就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。) G, @8 w7 m7 w- j( ?4 j$ a
准备奠基
" S% H5 a2 ^& O% b我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
# B  g- b+ @8 H4 m* d' Iinline bool CheckFileIsBar(int &file, const string szFileName)
  J- U$ e; w9 }7 c{4 [: B" h' _7 q1 a* ~* \" f. x' ^
string  szInfo = "";
* D, |3 T7 e+ [" q; g4 j6 _& Dbool    bRet;; a! E+ L/ {9 K% Y6 E
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);
2 T; A& v: j4 \7 g$ q+ g. _6 jif ((bRet = (szInfo == def_Header_Bar)) == false)- W0 k) G6 ]7 l! U# E5 e
{
1 z2 p, P; c; U  T& APrint("File ", szFileName, ".csv is not a file with bars.");
* ?. C% j! \# H  Q) q- _FileClose(file);
( q# q- [2 S; w2 I8 g% J}* r* a7 f/ ~8 L4 z
return bRet;3 s6 o( d4 o+ B+ X" ?& L- w2 `' y) B
}% m8 E: N0 l: o6 J* O: `  [+ S1 D
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
7 m: A- T+ u1 Q1 F( Jinline void FileReadBars(int &file, MqlRates &rate[])
- w3 d5 P( O, y" o. x{+ G8 m: }' f1 I7 d
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));
. I# H1 A. Q- w9 a( a0 _/ `rate[0].open = StringToDouble(FileReadString(file));7 |: m9 Z# G9 `) Q% e! ^9 F
rate[0].high = StringToDouble(FileReadString(file));3 l, b0 l7 k' M/ J& _( W
rate[0].low = StringToDouble(FileReadString(file));/ S# m8 j6 _5 q& v: [) n
rate[0].close = StringToDouble(FileReadString(file));
+ Y1 `8 Q# y* N7 F+ |2 e( ?rate[0].tick_volume = StringToInteger(FileReadString(file));' ]/ a3 s5 O( j! E4 U
rate[0].real_volume = StringToInteger(FileReadString(file));  o$ E* G1 [1 |2 q! E8 i0 l
rate[0].spread = (int) StringToInteger(FileReadString(file));
9 `# X' E6 l- [, g}
* B& T- j: |- w1 E它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:' b1 q+ L' }4 w3 I3 c# p- h
inline bool OpenFileBars(int &file, const string szFileName)
! q: k" @( U& T{* E- n. v! ?* S$ \
if ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)# s- K9 S4 [; z: O; E
{& y2 J& l* t! G; {( Z
if (!CheckFileIsBar(file, szFileName))3 N! Y. T+ ?4 I; R, l2 n8 P2 O
return false;, Y9 I1 |% D$ k5 ]  p0 ?$ D
return true;3 ]6 [1 O# z) ?! v8 _' p2 @
}1 ^4 S2 t$ b: l0 l6 x+ T# _0 K% t
Print("Falha ao acessar ", szFileName, ".csv de barras.");
9 Z' E$ X* `% Mreturn false;9 f# h4 y5 }. J2 Q( ~1 w4 v, `- X
}) K, M3 J  _! T# d! [  t
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:+ N% P, k+ M1 `4 k
bool LoadPrevBars(const string szFileNameCSV)
/ g. a& t" w0 N: @{" D9 B6 e+ |6 ~1 G. F5 l
int     file,7 ~8 f- M6 [. T. B. T
iAdjust = 0;
# X# B( V' x' C; qdatetime dt = 0;2 ?6 `+ W6 y" r2 R. s& j( k
MqlRates Rate[1];
! V" s, g! A9 ?: Uif (OpenFileBars(file, szFileNameCSV))
  }* e/ h1 I. M) f% R, \0 g{! |! i4 X1 l& L% Q) Y/ N
Print("Loading preview bars for Replay. Please wait....");
2 b+ P5 ]1 s9 Xwhile ((!FileIsEnding(file)) && (!_StopFlag))( n( z: U) L3 m1 t, ~8 V! d
{% Q. g0 b! y- F1 h4 ^: [
FileReadBars(file, Rate);
6 T$ X1 \! z; \4 k+ ViAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);
2 p$ Z" m6 b2 ^7 X5 d* n5 c' [/ X  hdt = (dt == 0 ? Rate[0].time : dt);' o7 [7 F$ n* @2 L& T) l" |& R6 R
CustomRatesUpdate(def_SymbolReplay, Rate, 1);3 z: C, M% u2 v3 K4 d
}
' M: k% ^1 t8 Rm_dtPrevLoading = Rate[0].time + iAdjust;
' E) [: ^/ R' j) k  j5 cFileClose(file);; @# M0 j5 |2 t6 y! l4 ?
return (!_StopFlag);' X5 o+ c. ]. Q6 e9 p/ Z
}% Q( m! r5 K) I- X
m_dtPrevLoading = 0;) T& e$ @3 @# Z5 K
return false;& P( B6 `- X: N& r; [& [
}+ [- l3 l8 ^7 ^% y6 U/ S* t
这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:
! s, ~" n* |- X9 U#define def_STR_FilesBar        "[BARS]"" A- v$ Z# A5 \7 _$ Y
#define def_STR_FilesTicks      "[TICKS]"
6 Q; L+ z* Q2 P, z/ s0 n#define def_STR_TicksToBars     "[TICKS->BARS]"
+ _$ a) j# e, v# c#define def_STR_BarsToTicks     "[BARS->TICKS]"
; P1 b! Z% X3 i这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-12 19:41 , Processed in 0.438775 second(s), 31 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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