私募

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

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

[复制链接]
发表于 2024-3-31 08:39:53 | 显示全部楼层 |阅读模式
规划6 ~* x( R0 {6 P) l
许多人可能认为规划很容易,特别是,由于它事关转换柱线,即始终把 1-分钟柱线转换为票据(我们稍后会解释)。 然而,模拟比表面看要复杂得多。 主要问题在于我们尚未清晰地理解票据的实际行为,就去创建 1-分钟柱线。 我们只有柱线,和一些它的有关信息,但我们并不知道柱线是如何形成的。 我们将采用 1-分钟柱线,因为它们所需的难度最小。 如果您能创造一个与真实事物非常相似的复杂走位,那么您就能够再现一些非常接近真实事物的东西。3 T$ r- T/ l1 \* K) l) q# Z
这个细节似乎并不那么重要,因为我们通常会在市场上看到锯齿形的走位。 无论走位如何复杂,这一切都归结为在 OHCL 点之间创建锯齿形。 它始自柱线的开盘那一刻,且需不少于 9 个走位来创造这个内部的锯齿形。 它总是在柱线收盘时结束,并在下一根柱线上重复该过程。 MetaTrader 5 策略测试器采用相同的逻辑。 更多详细信息,请参阅真实与生成的基差:算法交易。 我们将从这个策略开始。 虽然对于我们的目的来说并不理想,但它将为开拓更多适合的方式提供一个起点。
/ Y" L+ l, p$ f就我而言,测试策略器不太适合回放/模拟系统,因为在策略测试器中,时间问题并不是最重要的。 这就是,没必要以这种方式创建和复现 1-分钟柱线,因为其长度本来就是 1-分钟。 事实上,它甚至更简略,在于它与现实时间并不对应。 如果是这样的话,那么测试策略就变得不可能。 想象一下,依据跨越几天甚至几年的柱运行测试,如果每根柱线复现时间与实际不同。 这将是一项不可能完成的任务。 然而,对于回放/模拟系统,我们正在寻找一种不同的行动。 我们希望按照 1-分钟间隔创建一根 1-分钟柱线,尽可能接近这个目标。
( I% M; W0 E2 r0 a$ t! W7 i8 g+ o. M$ ^准备奠基9 \8 c, t3 F  U$ }6 O; z1 M* v
我们的重点将完全放在回放/模拟服务代码上。 此时无需担心其它方面。 故此,我们将开始修改 C_Replay 类的代码,尝试尽可能地优化我们已经开发完成并测试过的东西。 下面是类中出现的第一个过程:
) Q6 z3 c& w. J  o/ f- Qinline bool CheckFileIsBar(int &file, const string szFileName)- h( f( Q& @/ H( k3 j; h$ |
{: ?+ x2 N4 d$ g0 o& g
string  szInfo = "";
, y/ }/ Q2 ]) m/ Gbool    bRet;
: f* @. C* S( tfor (int c0 = 0; (c0 < 9) && (!FileIsEnding(file)); c0++) szInfo += FileReadString(file);
6 P: q% J2 M1 g# X6 o3 Tif ((bRet = (szInfo == def_Header_Bar)) == false)& Y9 d9 Z6 ~5 \% t$ z% Q) Q" A
{
( I. r8 E' ^. M$ q; B/ f+ ?Print("File ", szFileName, ".csv is not a file with bars.");/ o) y. m+ ?# ^8 I6 P# b
FileClose(file);# B+ B& e* S0 O* u- @- W
}
2 c7 k- [8 z" j4 x! ^9 v/ v3 b3 L  \return bRet;0 C! {( R& _; H; E1 Y5 a$ t
}9 T6 W+ V! G, t$ z) r
此处的目标是柱线读取函数,这些测试是为了判定指定文件是否为预览柱线文件。 这是必要的,当使用相同代码来判定柱线文件是否符合我们所需时,如此可避免重复代码。 在此状况下,这些柱线将不会用作预览柱线。 它们将被转换为模拟票据,以便在交易系统中使用。 有基于此,我们引入了另一个函数:5 q. E4 A$ S# T5 j% W3 E7 M9 q
inline void FileReadBars(int &file, MqlRates &rate[]), K/ O3 c. F: \7 T' o( _
{
# o& c, E# C# h0 urate[0].time = StringToTime(FileReadString(file) + " " + FileReadString(file));+ S$ l9 g4 P$ ~# V0 J1 @6 O# n
rate[0].open = StringToDouble(FileReadString(file));
! j2 N2 k6 n. F6 mrate[0].high = StringToDouble(FileReadString(file));, q% E. R+ C+ }8 S5 B- L5 {( h( L
rate[0].low = StringToDouble(FileReadString(file));- o  D9 J5 G3 G/ [# n* r: j& K4 D
rate[0].close = StringToDouble(FileReadString(file));3 l( M! }  U3 ~( q; R0 n$ s* \
rate[0].tick_volume = StringToInteger(FileReadString(file));2 B" J6 W" V- j
rate[0].real_volume = StringToInteger(FileReadString(file));, {$ }! \. R: m. B/ y
rate[0].spread = (int) StringToInteger(FileReadString(file));
! L4 g+ D' Q# B% T1 T- r/ }}
5 n1 J& D  \. \& R+ X; o它将从指定文件里逐行读取已有柱线的数据。 我想您在理解这段代码时不会遇到任何困难。 继续这个准备阶段,此处是另一个函数:5 s9 l! _4 F% q8 y$ z2 E
inline bool OpenFileBars(int &file, const string szFileName)! c# P; w# `) X% ?$ P; J7 e
{
3 ]  L5 W5 W3 L3 w' \3 lif ((file = FileOpen("Market Replay\\Bars\\" + szFileName + ".csv", FILE_CSV | FILE_READ | FILE_ANSI)) != INVALID_HANDLE)' @3 y/ V' G& U3 |6 {
{' h. t' }+ W2 I7 M
if (!CheckFileIsBar(file, szFileName))
( [% i; r7 T" b7 Ireturn false;
+ ~: L) S" b4 R* j& ~4 Jreturn true;$ Y9 s* ?. W0 g1 I: I& @7 b% W0 {
}
% }9 V6 J: t" Y4 J8 U, ZPrint("Falha ao acessar ", szFileName, ".csv de barras.");
6 d- W+ e0 q. m% Jreturn false;
* Z3 F" ?3 I! y, J# h0 R2 ]' R}
& V3 t5 @5 m; Q' ~1 V我们的系统现在已经完全集中化,能提供对柱线的标准访问:我们即可把它们用作预览柱线时,亦可把它们用于模拟,并转换为票据表示。 因此,之前加载预览柱线的函数也必须修改,如下所示:
" e) D% r' C" G  _3 Hbool LoadPrevBars(const string szFileNameCSV): ?3 l6 A" l7 V0 n+ a! ?
{
4 W, @# s: t: h! [int     file,( F+ B! K, d5 z" Y- R5 @# G' o; F% m
iAdjust = 0;
8 b, s% y8 V: Sdatetime dt = 0;
. `# ^, l9 }" f" R3 QMqlRates Rate[1];
0 c; D) c2 h9 f4 \7 }if (OpenFileBars(file, szFileNameCSV))
* d3 z4 B+ o8 o8 p+ X% E% B{
4 L3 E1 Z; j) S; b0 hPrint("Loading preview bars for Replay. Please wait....");
6 U# D6 B% H% ~8 l$ |3 A7 ^' `while ((!FileIsEnding(file)) && (!_StopFlag))( L: i5 m3 p5 [8 g' a( f2 q: _
{
1 D7 B8 x, U* M: c; TFileReadBars(file, Rate);
/ |& _; i5 l& n2 Z% x. f! jiAdjust = ((dt != 0) && (iAdjust == 0) ? (int)(Rate[0].time - dt) : iAdjust);6 o( W/ C! U  B+ M4 l4 v& I- F
dt = (dt == 0 ? Rate[0].time : dt);& |+ E- `, [9 Z" w8 Z% Q
CustomRatesUpdate(def_SymbolReplay, Rate, 1);/ \) d: Q9 {/ p- m
}6 Y( i! @+ e5 ~' d7 W: F) f9 a
m_dtPrevLoading = Rate[0].time + iAdjust;: H6 F& R- @( H. B
FileClose(file);! x  o  Z3 f: @
return (!_StopFlag);9 N2 l8 R+ |2 V! P0 \# f
}
0 t( A% H8 S- l" }( c8 Em_dtPrevLoading = 0;, c7 }3 u/ V" [* G- s4 ~
return false;8 s. |5 e+ G6 q+ c
}
% c& X& \1 S+ R& w7 d) b这个下载函数的工作方式并无变化,尽管现在有更多的调用。 从以前的函数中提取一部分,并在新位置加以运用,为我们提供了更高的安全性,因为所有代码都已经过测试。 以这种方式,我们只需要担心新函数。 现在地基已经准备就绪,我们需要在配置文件中添加新内容呢。 该函数旨在判定哪些柱线文件可用于模拟票据。 为此,我们需要添加一个新定义:
; f/ q5 e: m* ]0 p3 a#define def_STR_FilesBar        "[BARS]"5 ^6 _( P$ J1 `6 p! m
#define def_STR_FilesTicks      "[TICKS]"
/ p" L5 ]& X4 D6 \; ~) D#define def_STR_TicksToBars     "[TICKS->BARS]"  Z' Q& v8 X7 N; l" X) H
#define def_STR_BarsToTicks     "[BARS->TICKS]"
7 i' w7 |6 e9 V9 U, f这样我们就可以运行一个简单的测试,这正是我们开始进行模拟所需要的。
http://www.simu001.cn/x287867x1x1.html
最好的私募社区 | 第一私募论坛 | http://www.simu001.cn

精彩推荐

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-13 03:32 , Processed in 0.407773 second(s), 31 queries .

Powered by www.simu001.cn X3.4

Copyright © 2001-2021, Tencent Cloud.

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