私募

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划' C# G# E% [, E1 N8 r" V$ K
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
8 P* H+ {, K# r8 V  @# |9 h这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。8 a1 y9 Z' L+ s( W6 @3 s/ d; E' E
就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。9 j" P8 f" q, l# n4 S, k/ [5 p
准备奠基. A" }) \+ R/ ]6 K3 W
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
/ m3 \2 a6 c4 `" B/ Sinline bool CheckFileIsBar(int &file, const string szFileName)
4 K* R4 v/ I2 h* q" K, G{
- A( I8 r/ V2 x+ m( @0 Sstring  szInfo = "";" J! t3 m: D# `- C  o0 D
bool    bRet;
# n9 Y1 ?) x3 Pfor (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);: A3 d: n1 }. T, u3 V) r5 I2 b/ d
if ((bRet = (szInfo == def_Header_Bar)) == false)
0 i. _5 o9 l+ k7 y# x6 d! @5 N1 A{2 K! {0 K" A  B" `4 u- F) D
Print("File ", szFileName, ".csv is not a file with bars.");( w0 G6 H" O1 H2 @1 r
FileClose(file);& ?8 G, }$ n- i! K
}% Y4 y$ v+ L& q! R0 s- q
return bRet;
8 I2 A6 W* Y+ s, h, [; s) A$ S8 t}
- p/ c$ U& r* s  J  u此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:; l; g( v9 ]$ G2 s2 h
inline void FileReadBars(int &file, MqlRates &rate[])
6 `% C3 ?% h# i/ e{2 n3 l- J; d* [- i/ ?
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));
, ^5 i: [- |4 J: F: }* Rrate[0].open = StringToDouble(FileReadString(file));% I0 [: _# v( }  }/ c/ M; m
rate[0].high = StringToDouble(FileReadString(file));! Z+ y  t! n# v
rate[0].low = StringToDouble(FileReadString(file));/ v: c5 P" J* ?% z8 ]
rate[0].close = StringToDouble(FileReadString(file));
! L' l* A2 F) x9 N1 Mrate[0].tick_volume = StringToInteger(FileReadString(file));
  [9 m4 U" E" V; j" Hrate[0].real_volume = StringToInteger(FileReadString(file));
9 ?( e; h0 I+ N7 i4 p/ _: o  ?rate[0].spread = (int) StringToInteger(FileReadString(file));) s& d. C# g4 K; T( R9 f( r' w
}
4 z3 y7 C) ?, N: F它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:( @1 P# I1 j) z
inline bool OpenFileBars(int &file, const string szFileName)0 F9 V- s1 D' {
{5 V  y, A& E8 x( A5 A- x
if ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
8 ]! y, a9 @$ r/ J7 G{
* M: i4 o4 M% g  @" xif (!CheckFileIsBar(file, szFileName))
# {) J# a7 ~5 |8 }& Y8 G: l6 v7 areturn false;
" y' D* W% \  ?) k3 j  v9 r' T' v" T; Rreturn true;( p. C. @1 l# c. Z& M5 k" D. F
}2 u9 {. c  {6 P0 q
Print("Falha ao acessar ", szFileName, ".csv de barras.");$ c4 \6 E) h+ k% h
return false;
0 V( b1 Q8 M9 h2 l}" K0 r+ s( Q; ~' O/ C; \3 S# a
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:3 b8 w+ s/ T0 {" J& U5 t
bool LoadPrevBars(const string szFileNameCSV)
( O, \! v$ O! B7 u( |. i# B{6 e" N, i, [2 Q/ @8 R* r
int     file,
$ I1 I8 W3 d( i, y8 o- U) @iAdjust = 0;
; R- H1 N( A! F! r" i- R* v& qdatetime dt = 0;
, p4 x% [: a  P0 WMqlRates Rate[1];+ u; Z9 l6 j0 g: i! _- a
if (OpenFileBars(file, szFileNameCSV))( M5 O* q* G% ~' ], {
{
- s$ l/ R4 i2 s6 m# EPrint("Loading preview bars for Replay. Please wait....");5 J$ V& S+ m  B0 }- s
while ((!FileIsEnding(file)) && (!_StopFlag))
/ ?  B  G& K+ [/ T# ?0 I{
% q. _7 ~9 u8 d6 [. w! k8 OFileReadBars(file, Rate);- d! O6 J- k. C5 n
iAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);
$ P- ?+ b3 S& X: t$ P% |5 d* Z4 Y7 ]dt = (dt == 0 ? Rate[0].time : dt);
% w. @5 k5 \2 jCustomRatesUpdate(def_SymbolReplay, Rate, 1);
; j! \( L+ ~, o- {6 ?) }. P+ f; H}
; H4 L7 e- L( P  ^. Nm_dtPrevLoading = Rate[0].time + iAdjust;
+ y5 k9 f0 m1 m' s  L- _FileClose(file);0 f  b& T" Y# S- M9 N
return (!_StopFlag);
) W2 _: e2 a. y. c. W* w( |( t" T# t}- V! \6 u+ N3 f: a
m_dtPrevLoading = 0;
/ T! w6 N9 }) T2 [, K4 r( Hreturn false;
8 J4 ~9 j7 u8 j" O2 `3 B. z}
; B% B! n2 w+ G- V0 A" U/ Q这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:
4 y- }' m4 d* b+ I  c! o#define def_STR_FilesBar        "[BARS]"
6 d1 r3 ~. [. q7 ^% X2 d6 I#define def_STR_FilesTicks      "[TICKS]"
: R3 R7 {9 T/ i/ ~3 o. ?+ {/ y#define def_STR_TicksToBars     "[TICKS->BARS]"
7 f5 ]. U: I: G) W  E#define def_STR_BarsToTicks     "[BARS->TICKS]"! U  |, R! P# E1 ~( j, h# v: _2 y
这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-23 11:39 , Processed in 1.252893 second(s), 32 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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