私募

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划
8 V' O& V: v2 _4 b7 \7 V% \许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
! i" ^: L2 n) ^  p" Y4 M$ t这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。) Y9 G- y# ~( J1 b* \# K1 o  G' i
就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。
# T+ k: q+ G( h, A  P& V准备奠基
; F$ M% D9 X' T( F) I- j我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:& ?7 P& t9 O6 F4 `. ]) f
inline bool CheckFileIsBar(int &file, const string szFileName)  o6 t( ?2 @  O( g( X/ j) ^# z
{
% z+ [) n) y" [) Bstring  szInfo = "";
% w, k* {  G, M- Mbool    bRet;
: H' K. P9 E; r3 I/ i* mfor (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);
: }# r* V, u. Q, B9 R  aif ((bRet = (szInfo == def_Header_Bar)) == false)" Y) K3 K" h/ j( X- S5 U
{2 {& e' X( Y: u, a# u) h0 p
Print("File ", szFileName, ".csv is not a file with bars.");
5 M- L5 V# k, E4 i  eFileClose(file);6 v9 h( R( X3 o& f$ b1 {
}! r( t/ {# A/ F# E/ J# l
return bRet;( U8 h  @- [4 I( i) ^; P, @
}
7 y, l1 e+ p4 T: R. g$ a: V# d此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
8 v. C4 B' y0 I0 e- k) W2 y$ rinline void FileReadBars(int &file, MqlRates &rate[]), \8 l( u" D# O# x, D2 S5 N
{8 I# i. _+ {( Y* i3 e4 h; [
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));
% K, }7 P. z' M3 \# m  C# Hrate[0].open = StringToDouble(FileReadString(file));
" v# Q- _0 t( t/ Y* zrate[0].high = StringToDouble(FileReadString(file));6 j: j- f% b$ o4 x7 C" _
rate[0].low = StringToDouble(FileReadString(file));* ~: b* m  e0 y( \" t+ A
rate[0].close = StringToDouble(FileReadString(file));1 {7 |" K% r' I0 [. J! R6 W
rate[0].tick_volume = StringToInteger(FileReadString(file));* a! n- ~3 X% A) T' s. X
rate[0].real_volume = StringToInteger(FileReadString(file));6 d! A3 n  k- J4 N; F) p  r
rate[0].spread = (int) StringToInteger(FileReadString(file));5 ~# H+ B0 m. C1 p; j
}& W: K$ k  B; g$ y6 K
它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:+ O' j" a# Q# }9 u$ g* Z
inline bool OpenFileBars(int &file, const string szFileName)
! r3 R- H! o$ J6 {- r; Z6 j% f{
- E9 j* |, m( d4 O. _: V+ qif ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
, M1 @3 f' \; W! F6 \{7 ~+ x2 {- C* `6 d; [
if (!CheckFileIsBar(file, szFileName))/ s  F  `+ }, V8 D8 U" G2 O# Y! w+ y
return false;  D, V* v. G! r& j
return true;% U, m- [9 M/ X  e
}" i2 Z% }- @* ~/ q8 g/ S
Print("Falha ao acessar ", szFileName, ".csv de barras.");6 W3 B* p; I* L3 i6 B
return false;! T7 i2 m3 h. z# u
}) N  w$ X+ r8 ~8 w) a
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:, B( I0 K6 l; R) Q- w
bool LoadPrevBars(const string szFileNameCSV)
' y$ y# c& o- y. Q5 A% [{! H+ h/ W4 n6 O$ U1 e
int     file,* B* F9 W3 u+ t% o6 J3 Z* i9 t
iAdjust = 0;
5 H+ T7 X9 N/ y  [* c! w! tdatetime dt = 0;+ b/ D  ?* M& H
MqlRates Rate[1];
, _& e* \9 ~( T; {$ j7 Jif (OpenFileBars(file, szFileNameCSV))
4 B4 F% P, x, t% a{
6 x5 `2 _, C9 X$ x8 y' ?Print("Loading preview bars for Replay. Please wait....");
) t5 Q* C! H6 X; P7 vwhile ((!FileIsEnding(file)) && (!_StopFlag))) O' |3 a* _2 Z  M3 c
{
( L: u# t( r* }: @) pFileReadBars(file, Rate);/ g. |) f4 T- S( @- S4 y0 a# @  |
iAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);  P) P7 P5 i3 Z: a1 p( z, X' ?6 z
dt = (dt == 0 ? Rate[0].time : dt);
: \" l2 h7 l. r0 F5 ^" TCustomRatesUpdate(def_SymbolReplay, Rate, 1);
- f4 N5 n5 w3 t, x/ Y" Z' W}
4 ]' a1 R# M9 Rm_dtPrevLoading = Rate[0].time + iAdjust;
* {/ n( {; Q9 n4 P& oFileClose(file);+ B* [2 o1 J; N# U  a8 `) ]
return (!_StopFlag);. \2 }  W" R  T1 ^8 T7 l" [% f4 H
}  |0 c8 M' q  D6 x
m_dtPrevLoading = 0;  n1 j* f" F) K7 q6 u6 ], \4 Y
return false;) ~8 W3 M. G8 K
}
1 T5 \) O9 S7 a  E" T这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:& X+ L$ Q9 O, X1 s) B6 T
#define def_STR_FilesBar        "[BARS]"
. P  l* Y5 ?1 n2 x" ]: }#define def_STR_FilesTicks      "[TICKS]"3 C/ D* W  ]; e8 ]# K
#define def_STR_TicksToBars     "[TICKS->BARS]". ]  B( e" _: ?8 S4 D* r' r
#define def_STR_BarsToTicks     "[BARS->TICKS]"
- @* g0 m. R$ x+ p& f& E这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-10-21 19:27 , Processed in 0.406488 second(s), 32 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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