私募网

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划; C* [$ q' D2 w9 O9 [& @% I
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
/ _7 O7 T2 _) Z) `5 M) p! M这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。7 r0 x: g* e0 N- _" Q
就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。6 m+ _  ^& \( W  I5 C& r& |5 I6 Q
准备奠基
4 s, q  u3 e/ Q1 H5 ?. j我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
! r2 E6 ?( |( T7 g5 [8 Rinline bool CheckFileIsBar(int &file, const string szFileName)
" x: g$ H, h* l2 D4 Z! M* L! E5 [{9 n$ c: j& [. k" c' t
string  szInfo = "";- S5 G2 j% |. e% T
bool    bRet;1 x+ ]1 S3 b' W0 u% a4 z
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);3 y9 |8 ?7 }- i8 }. b8 Z2 H
if ((bRet = (szInfo == def_Header_Bar)) == false)
! |. A' S7 b* N2 C{8 ^3 F2 T; e4 z$ e9 P
Print("File ", szFileName, ".csv is not a file with bars.");. x) T; w  i. d3 g8 x
FileClose(file);
' J9 C- n" b4 d5 M}* {8 s0 x* ?  s# [  B
return bRet;7 S3 g$ C3 m* x0 h& i: r: L
}: {/ Z8 M( {8 W$ c+ n
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
4 d1 N% d2 D# ^3 G+ D3 Rinline void FileReadBars(int &file, MqlRates &rate[])
: ~) T8 S; N9 T& \4 K{/ c% W! i( x. J
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));% _& R( x( K+ e# N( R8 X; J
rate[0].open = StringToDouble(FileReadString(file));
3 f! {/ l; O' {rate[0].high = StringToDouble(FileReadString(file));
0 {$ ?$ @* i/ A9 Brate[0].low = StringToDouble(FileReadString(file));3 Q( I& U3 Z" G# x3 U* M1 ~
rate[0].close = StringToDouble(FileReadString(file));) R9 y) J3 c% z2 ?  c( v+ I0 \$ W
rate[0].tick_volume = StringToInteger(FileReadString(file));  t/ @5 T7 n" c$ Z
rate[0].real_volume = StringToInteger(FileReadString(file));, }3 R$ T' P! Q; a6 R  Z
rate[0].spread = (int) StringToInteger(FileReadString(file));
7 `# U( h/ Q) k2 q# p" g}
2 k& y) p0 G' _0 ~它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:4 u1 L: k( ^7 Z+ {/ Z5 u
inline bool OpenFileBars(int &file, const string szFileName)7 y+ `$ p( L2 D5 W5 K+ M7 D; k6 g% I3 c
{2 s7 T+ z& v, g
if ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE); s+ ~# |) z) K& W4 I: L7 i
{
) Z3 u; O9 \7 y% c, d% Oif (!CheckFileIsBar(file, szFileName))6 ?& s5 K+ Z# |
return false;
$ y! r2 ^% ], y5 Z# R2 Greturn true;
2 r* r5 R+ K- g, M}! U& }# }. a8 y' Z! P
Print("Falha ao acessar ", szFileName, ".csv de barras.");" Z- b! }* l7 Q( N  l6 I6 N
return false;3 Q! K9 r- w% g- }$ U1 m5 |
}' l, T: U, r: j; d* Y/ l8 G* Q% @
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:' r# i7 k4 g$ R, k8 n3 {! W$ i
bool LoadPrevBars(const string szFileNameCSV)
2 U" ]4 F! q( Q9 F: F! F+ ~  o{
" T0 M# i6 e+ X& q& }$ v: q, u) yint     file,
0 b% }: A' V* R1 r3 i# M- B8 liAdjust = 0;
& e6 o" `# X( P5 {) q, D' Gdatetime dt = 0;
8 G  u9 I6 b* A2 i! |1 EMqlRates Rate[1];( B" M9 y6 [7 y( i$ o0 i7 [
if (OpenFileBars(file, szFileNameCSV))0 Q5 k  R5 L6 ^3 U' ^7 B$ y
{
: U0 q% c5 a; z  E2 nPrint("Loading preview bars for Replay. Please wait....");
* n+ _" a( C, T% h2 awhile ((!FileIsEnding(file)) && (!_StopFlag))/ l  `; H$ m3 ^
{& A7 Z  H6 `$ H: q+ S
FileReadBars(file, Rate);
4 @, Q4 K2 N" X( E7 OiAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);
3 d5 y( S* ~" k. \0 D% V5 Pdt = (dt == 0 ? Rate[0].time : dt);* i  x7 S$ L6 Q: t/ `- X- k! E( U
CustomRatesUpdate(def_SymbolReplay, Rate, 1);
& x+ V3 w3 S% I! j. d) u}
  C4 q2 s  V9 l1 Qm_dtPrevLoading = Rate[0].time + iAdjust;+ ?. S6 Y% |( B/ _& T2 I( @
FileClose(file);
+ @/ w3 y4 s3 J3 v  Q1 k/ [return (!_StopFlag);
" e1 }+ g( k! p2 F& X9 R}2 A5 i) Z! m6 h# x8 u
m_dtPrevLoading = 0;
; K2 Q# {4 T( Q) ?return false;
% G5 w# I$ [4 k+ [! Z+ C6 U. B}
$ }9 E8 }5 J6 `' X7 h) S这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:2 v4 y9 }$ z/ j# I$ s4 N
#define def_STR_FilesBar        "[BARS]"+ G7 e, [2 H& O* v, u4 ]" P
#define def_STR_FilesTicks      "[TICKS]"
5 q% l! C( h* s6 w0 @/ y#define def_STR_TicksToBars     "[TICKS->BARS]"
7 G7 W$ _9 y: F# L* r7 g4 v#define def_STR_BarsToTicks     "[BARS->TICKS]"6 Y, m3 {5 |% o
这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-19 01:14 , Processed in 0.554666 second(s), 31 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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