四目观天下

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划
# ^) l7 V" U# o$ B+ }! A) U许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。
( u4 q( H( n" U+ c6 z5 m" ]' I. Y这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。
  f' p1 U3 H+ _5 Q  c( e就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。4 o+ H; M) ~5 t. E; g
准备奠基
4 C  Q5 f+ _9 o" D5 L我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:3 v2 T& e- ~3 y+ ?  g4 `. R
inline bool CheckFileIsBar(int &file, const string szFileName)$ w8 h6 d. f2 i/ h0 \
{
$ I/ J; F! ~8 V- ~0 b( R/ \string  szInfo = "";8 y, S: y; C8 n6 b, m$ t" a# A
bool    bRet;
: S- x+ r6 K8 `; ^) M8 `7 {for (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);
) V, f% P2 I3 `7 D' Kif ((bRet = (szInfo == def_Header_Bar)) == false)
# V" p, y( Z3 l# N{
% {3 _6 d# c+ T) d6 SPrint("File ", szFileName, ".csv is not a file with bars.");$ C' o  p! X; Q1 W! w4 S
FileClose(file);" c3 k! p; [, g
}7 O# n6 ~6 w/ \- v; f
return bRet;
- q' `/ [* @" r( z: b}& R: u* v8 [8 c- M
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:
+ s2 s  V3 v6 L" G5 m) `inline void FileReadBars(int &file, MqlRates &rate[])5 X& s/ f: |, |+ }5 R
{0 Q) r5 v7 {& k; g; V7 {/ f7 G
rate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));! j7 h6 @4 x9 }1 Q& s
rate[0].open = StringToDouble(FileReadString(file));# P  j' u) p1 U: d( L; O+ U* g
rate[0].high = StringToDouble(FileReadString(file));
) U. Y5 `! L/ ]% y" |' arate[0].low = StringToDouble(FileReadString(file));
& ]( _0 u' E) Z! Wrate[0].close = StringToDouble(FileReadString(file));
1 u& A; Y0 \1 mrate[0].tick_volume = StringToInteger(FileReadString(file));
1 D$ ?' M4 E4 o: k$ Arate[0].real_volume = StringToInteger(FileReadString(file));
& U+ C, a! g& E: U9 {& C* p0 krate[0].spread = (int) StringToInteger(FileReadString(file));3 s; b( j  i7 h, j
}
+ D. K( q2 F: z5 A' I3 |, C: X它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:9 z, F) s1 ?7 a( p, b) k5 L9 \' W
inline bool OpenFileBars(int &file, const string szFileName)
3 S4 ?* x5 k6 _  k# C# A{# f" _' ~  A4 x% x2 Y. K6 I' E, k/ P
if ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)
' V$ V3 ]$ f* b* G/ y: y; L* e{/ V0 n$ C5 g* o! H6 B6 s
if (!CheckFileIsBar(file, szFileName))4 M5 T+ i- f" |" w) b& C' P
return false;) e& q- t/ W* W4 A* J/ q
return true;
. T' ^: W6 a, L. y}
+ B; h) Z6 d! `Print("Falha ao acessar ", szFileName, ".csv de barras.");# m8 R( g! [/ Z, ~0 S3 B& i
return false;
8 D, j1 G6 ^; l. Y' l! O4 a0 z}) m) C# {( u% h+ |+ m' Y8 O
我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:5 w9 a' b. J; V% U. l
bool LoadPrevBars(const string szFileNameCSV)
! Y( X+ e5 T9 n9 I8 V6 Y{
& |# d4 T( V% A( O* T' Q& Jint     file,, k- I' S! C$ T; R% v9 Y4 b6 b
iAdjust = 0;, V0 N. O8 g# q2 f: p
datetime dt = 0;
0 e- ?7 }) o0 Y0 G7 v/ `MqlRates Rate[1];
7 j" m5 h, X* U4 Q$ I$ Wif (OpenFileBars(file, szFileNameCSV))
) W$ Y" H6 U7 ?- ]# ^/ `{' G+ v# }- a" ^0 ?0 P- H% N0 ~5 E
Print("Loading preview bars for Replay. Please wait....");
$ b6 E3 v. y, w; T/ |while ((!FileIsEnding(file)) && (!_StopFlag))4 ^; b9 M6 ?: U: R* L" I: d1 }
{& Z8 E# H  m0 i( M
FileReadBars(file, Rate);
0 Y8 }8 `  T& v3 V0 u3 @iAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);8 ]& t0 {5 _8 R; ?- X( o% S
dt = (dt == 0 ? Rate[0].time : dt);
5 F& }/ K0 y0 M6 G/ ?* U0 O" ZCustomRatesUpdate(def_SymbolReplay, Rate, 1);+ f# i% S  C; t( d3 \0 y1 c2 T
}# \: v7 B- f# w1 t, t* s
m_dtPrevLoading = Rate[0].time + iAdjust;
/ ~6 ?8 w, ~1 B) {FileClose(file);1 Z+ k0 W+ i# |2 \9 B! J
return (!_StopFlag);
- C, B* e1 A9 R3 @- E3 p}
# M2 x1 w" Z$ K5 x% V+ l+ K( ]; Im_dtPrevLoading = 0;2 i7 r+ Y# z) u. n5 a$ V. ~% @( z$ ^
return false;
/ t2 {: J4 ?6 [" M}
$ U! o3 o8 E( p8 }% o7 H4 B, ?这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:
7 \$ p, ?' v! l- j$ g#define def_STR_FilesBar        "[BARS]"
$ ?+ X! j% ]: z+ Z9 a$ G#define def_STR_FilesTicks      "[TICKS]"
6 ~. E# O7 w, ]1 [" W. i: ?* v2 f1 C: y#define def_STR_TicksToBars     "[TICKS->BARS]"  A9 B  d! s) |4 {( l2 n
#define def_STR_BarsToTicks     "[BARS->TICKS]"! K( L' r  Z$ I" d
这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-5 08:25 , Processed in 2.319631 second(s), 31 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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