私募

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划0 h' M) H, b% T0 T, c; m* k
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
* }' S$ a- G  l- h这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。
5 X7 I/ F" {% t8 f4 {9 @就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。7 m1 z8 D% h. \3 }% c/ X1 r
准备奠基. P9 F) \- a% D6 u2 g! h
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:/ t3 L' l+ d5 Z: r; R( @
inline bool CheckFileIsBar(int &file, const string szFileName)
$ F) [9 o2 `$ Q+ h/ V) \( B{
) e& c" n$ @' N! o3 [7 u, M" estring  szInfo = "";8 j$ E' c& Z- o5 Y3 g) l9 S3 U' G
bool    bRet;  {& M* M2 S' [5 H  E
for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);
0 @+ [7 b* i0 X! A9 }! S7 d' nif ((bRet = (szInfo == def_Header_Bar)) == false)& U1 O8 V* S8 N+ J3 y# H9 R& W
{
/ m' b: {& o4 T5 ZPrint("File ", szFileName, ".csv is not a file with bars.");4 o# z+ U% O0 H' [& K" E
FileClose(file);
1 h# g. d, z4 ^) z}# k5 T; y* ]' t& {( b1 z
return bRet;2 \+ n6 u6 U6 n) g0 v2 _
}9 [7 a. m" p- G( s5 a$ G- y6 T/ l
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:0 `: o" Q3 O  b, W) H- J/ P
inline void FileReadBars(int &file, MqlRates &rate[])
/ e  `" _' y1 I8 `* ]{5 u3 k& V6 G+ E% h, `# d
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));
  I1 l- P; U8 i1 f: ^rate[0].open = StringToDouble(FileReadString(file));
  @) K3 M" i& z5 g6 g( e6 _rate[0].high = StringToDouble(FileReadString(file));
0 d7 L2 C4 D& e3 v. G. J0 @rate[0].low = StringToDouble(FileReadString(file));2 F4 S& P: T; s5 N) k6 `7 n
rate[0].close = StringToDouble(FileReadString(file));3 I+ ]; ^3 L! z  x# {3 b
rate[0].tick_volume = StringToInteger(FileReadString(file));" |/ o- L# c9 }3 E
rate[0].real_volume = StringToInteger(FileReadString(file));# M* ]6 N) {3 ~: K. }
rate[0].spread = (int) StringToInteger(FileReadString(file));
2 |4 _" B. u5 ^$ M9 K% J}
1 p/ _+ E" D( X5 p它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:, G! l. ~4 t4 g0 B/ ^
inline bool OpenFileBars(int &file, const string szFileName)/ s' P$ W7 P/ g7 i3 l) m. T! K
{
: _/ R7 s9 A1 a( N$ }: zif ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE); M4 o* U7 B# W
{
+ y8 i  U- b/ H9 j" X4 z% _  |if (!CheckFileIsBar(file, szFileName))! ?& v3 O9 ~3 P! N; I- x
return false;
! e* {" [4 a) M: e. A3 Zreturn true;
  @7 X3 F' q2 n+ D}
. E7 F/ W. w2 b; \7 [' e# JPrint("Falha ao acessar ", szFileName, ".csv de barras.");* B) h" f2 u- `( o# g8 W& }1 i
return false;
8 d5 V4 a# A& l* ?0 Z2 m}
4 |2 w( z/ b% q! I3 e4 c我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:
, K3 r! U2 o- Q  h- u) }bool LoadPrevBars(const string szFileNameCSV)5 b! R5 w# d2 R1 X" f" z# B( `: x
{' H1 h  D) U! w! }; k& f" _- F* @
int     file,
5 k" {/ Q8 d7 d7 ~iAdjust = 0;
: Z1 }  a' ~8 l7 C% d- i: adatetime dt = 0;. e9 r9 `6 ]: ~& L1 i4 o: @  g
MqlRates Rate[1];# g) A* s  W( ?6 M2 L
if (OpenFileBars(file, szFileNameCSV))
3 f8 \* f0 D) T0 D* n/ n{$ @; N" ~( \+ g
Print("Loading preview bars for Replay. Please wait....");
! D4 @/ i7 i$ Z: }while ((!FileIsEnding(file)) && (!_StopFlag))
7 ?5 m# I$ D4 [; ?8 R% ~$ U+ n1 m9 B{
8 v: m8 r" A3 j2 WFileReadBars(file, Rate);
" }4 j7 R+ O0 L; Q& w* H: GiAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);/ I+ F1 g9 [5 v4 }" ]% ~! ?
dt = (dt == 0 ? Rate[0].time : dt);
9 E3 [% z+ r8 o1 R, o# vCustomRatesUpdate(def_SymbolReplay, Rate, 1);
3 x3 p( R* |& y6 i" x}
  Z" a* l$ b8 h- z8 _m_dtPrevLoading = Rate[0].time + iAdjust;
" ~* v9 u! T$ [, ?3 DFileClose(file);. V: v) G% \( r" R. M# A
return (!_StopFlag);
8 S+ c" K7 z0 J4 [* c0 r}
7 o, K2 s0 ^8 {$ t2 B! ~m_dtPrevLoading = 0;
& e2 g1 Q. w  O. p% h  Greturn false;
0 |$ ~9 L. a( R* ]& U" J}2 d) ]  L* V9 X+ O) T: M# x5 P
这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:9 P. T: H  V6 |# [
#define def_STR_FilesBar        "[BARS]"
- W, G& U0 w- G9 m; t#define def_STR_FilesTicks      "[TICKS]"; N: b6 @9 ~. D
#define def_STR_TicksToBars     "[TICKS->BARS]"
0 m. [. d+ Y( h' t5 d#define def_STR_BarsToTicks     "[BARS->TICKS]"
% ~9 H5 r9 \& K8 @4 s这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-9-13 04:04 , Processed in 1.605500 second(s), 32 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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