私募

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划
: S" }) |1 Z( P( I/ j, K) Q许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
, [' e+ D1 I- Q! u' ~' E  o这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。
" R9 g. ]  N* {7 _: W就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。! A1 n( l4 W2 t- C! l# \
准备奠基6 m. V9 b' h: V# d! F
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
: ?, |0 Y" v" V8 d8 n. pinline bool CheckFileIsBar(int &file, const string szFileName)8 z8 |+ b) X; q6 {) H' X/ x
{) k4 J& N2 l8 K
string  szInfo = "";
& o5 c( m) M, ]' c1 ~' O# R. u) ?bool    bRet;" X' d  M+ c; k  e: m
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);2 ?* h3 B* `, U- M! F$ r" x
if ((bRet = (szInfo == def_Header_Bar)) == false)% L; h- d, f$ Z; t- H' X
{5 g% y+ q; P& l# h) Y4 ~5 l
Print("File ", szFileName, ".csv is not a file with bars.");" g) a$ k6 J# H( r. H# b) }
FileClose(file);
& S( C* T; o. f+ m' ~+ @; n}
0 W' [4 i' M) @3 Rreturn bRet;9 ^) ]" t' ^* a- |9 S, L/ ^
}
! L7 A" T5 f2 ?# S7 E9 W此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
8 X( F* s% M( Minline void FileReadBars(int &file, MqlRates &rate[])
/ f2 L6 R+ o9 Z2 F; ?; e5 L{+ R  v+ V* D" a1 B" B. ]) u
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));
/ x& s+ A% u/ A- \rate[0].open = StringToDouble(FileReadString(file));
. d2 D: n% N+ U( J. `- Orate[0].high = StringToDouble(FileReadString(file));
; \8 e& @* w$ _5 h# I! Z$ Orate[0].low = StringToDouble(FileReadString(file));
4 J4 a- V+ }9 V2 ?/ t3 i) a/ b; `rate[0].close = StringToDouble(FileReadString(file));: h1 n/ i' R% F
rate[0].tick_volume = StringToInteger(FileReadString(file));" q& X* k1 ]3 s7 x  H8 C: W6 u
rate[0].real_volume = StringToInteger(FileReadString(file));
1 [, r2 b- S0 ^* m0 ~( srate[0].spread = (int) StringToInteger(FileReadString(file));
5 w( F0 |) {6 x* G. l- A' P}4 }. C1 b5 b9 Z; Q* n
它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:
4 p8 X: e% V6 c- }& p* Qinline bool OpenFileBars(int &file, const string szFileName): k) P0 o2 E8 l# I( _
{
. f5 X; A: T! H# Tif ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)5 H0 Y! l5 n$ F; @$ [, e
{
0 q$ d6 q( V7 A: P. Bif (!CheckFileIsBar(file, szFileName))$ k' {* M( v0 f# V
return false;/ e- l2 g3 _8 A# J9 b
return true;
9 N, b% W8 O6 |+ M: _}
9 f4 w8 y# j# h' E- yPrint("Falha ao acessar ", szFileName, ".csv de barras.");6 v8 R; g5 X' }$ l  j/ J
return false;4 V! v4 G0 x$ u, Y# k( Z
}4 R" t! K2 N! _7 J9 ~) K/ N- Z
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:/ g  _* E+ x7 D& s& i9 O
bool LoadPrevBars(const string szFileNameCSV)' C* B( \8 Q  d% d
{
3 ~- C0 D+ p" \6 ?int     file,
$ ?5 K8 c' B( `6 I% K9 Q& D5 g" CiAdjust = 0;
: G( A1 N0 U& X! U2 S3 M; s. Udatetime dt = 0;
/ X5 a7 S% H6 `5 E3 d5 ~MqlRates Rate[1];
& }* @% V% A+ L0 f2 Sif (OpenFileBars(file, szFileNameCSV))  c1 w& E7 ?! V
{  y5 a( g  A2 q: t6 l6 N
Print("Loading preview bars for Replay. Please wait....");
$ Q- y0 k* K, v) swhile ((!FileIsEnding(file)) && (!_StopFlag))' O- M0 ^( s% t- a" U# k; `
{
+ B( D0 p$ `  Y5 {. \; h: A" l0 xFileReadBars(file, Rate);) l; c2 q5 H0 m1 @5 A) D* L
iAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);4 X6 A* `0 i* W. M! m0 K
dt = (dt == 0 ? Rate[0].time : dt);
# q0 ^. p! J% a' E: q" S+ SCustomRatesUpdate(def_SymbolReplay, Rate, 1);1 h) N8 t0 K4 M% l: ~' Y$ c( K
}
: e$ E0 t( F, C2 c9 nm_dtPrevLoading = Rate[0].time + iAdjust;
' f7 R2 N# F: ^5 K3 Q9 T8 DFileClose(file);
4 O& P. Q2 |3 }+ n, h8 ureturn (!_StopFlag);7 E1 s5 E! ?) r7 ]
}
# r* t1 y/ t4 \& H0 fm_dtPrevLoading = 0;( P! O( [, Z' T" [1 I, ]! x; m3 q
return false;) |  D! V& v4 J7 f% f$ j
}: J& F/ t1 \4 {2 [% a
这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:$ |( K( o. t0 G  C1 N; b# N
#define def_STR_FilesBar        "[BARS]"
! w1 a$ ?, Q7 B( ]#define def_STR_FilesTicks      "[TICKS]"3 t4 y$ m; z' P6 @. V2 |5 a1 O6 V
#define def_STR_TicksToBars     "[TICKS->BARS]"
6 G: R  t) j3 @2 ]#define def_STR_BarsToTicks     "[BARS->TICKS]"
$ D2 m' ^# X9 ~' ~0 Y这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-2-23 05:51 , Processed in 5.752854 second(s), 31 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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