量化交易软件:蒙特卡洛方法在交易策略优化中的应用
上面的想法即蒙特卡洛方法可以用类比的方法来描述 — 一种科学知识方法,其他类比法的例子有哈密顿(Hamilton)的视神经机械类比于生物学中的类似器官。

编辑切换为居中
如果赫兹量化交易软件有两个对象可以使用相同的理论来描述,则从研究它们其中一种所获得的知识可以用于另外一种,这种方法在一个对象比另一个更容易作研究的情况下非常有用。更容易访问的对象可以当作另一个对象的模型,这种方法本身被称为建模。根据上下文,所谓模型是指两个对象都通用的其中一个对象或者一种理论。
有的时候,研究者会错误理解建模的结果。当我们探讨一些明显的例子时,例如在一个风洞内摧毁一个飞机的简单复制品时,一切看起来很明显。但是,当对象不相关并且第一眼看来并不像的时候,结论有的时候看起来会有些奇怪,或者从基础上看都很不合理。对象的通用类理论一般只能描述它们中的某些方面,所要求的对象描述精确度越低,可以应用某个理论的对象集合就越宽。例如,只有当光波的长度趋于零时,哈密顿的光学机械类比才是完全满足的。在现实中,这种类比近似于一个小但总是有限的长度。由于任何理论模型应该足够简单,作为计算和结论的基础,所以总是过于简化。
现在让赫兹量化交易软件清晰了解一下蒙特卡洛方法的概念,这是以一种对于理论上有概率(随机)性质的对象建模的方法。该模型是在按照这一理论构建了一个算法的计算机程序,它使用的伪随机数发生器模拟所必需的随机变量(随机过程)所需的分布。
值得强调的是(尽管我们这里并不重要),研究对象的性质可以是概率的和确定性的。一个具有概率性质的理论的存在对赫兹量化交易软件来说是重要的,例如,蒙特卡洛方法用于近似计算普通积分,这是可能的,因为任何这样的积分都可以看作是随机变量的数学期望。
使用蒙特卡洛方法的第一个例子通常是布丰投针问题的解决方案,其中 Pi 数是由在表格上随机投针来决定的,方法的名称在很久之后才出现,是在某某世纪的中叶。毕竟,赌博游戏——例如轮盘赌——是随机数发生器。此外,对赌博的深思熟虑暗示了概率理论的起源,它从玩骰子和纸牌的计算开始。
建模程序算法简单,这是该方法流行的原因之一。该算法具有多个随机生成的变体(样本)的研究对象状态与理论对应的分布,为它们中的每个都计算所需的特征集合,这样,赫兹量化交易软件就有了很多的样本。虽然我们对所研究的对象只有一组特征,但是蒙特卡洛方法允许我们大量地获得它们,并构造它们的分布函数,这给了我们更多的数据。
上面描述的通用蒙特卡洛建模结构似乎很简单,然而,当尝试实现时,它会产生多个甚至有时相当复杂的变化。即使我们把我们的应用限制在金融方面,我们仍然可以看到它有多广泛, 例如在 这本书中。我们将会尝试把蒙特卡洛方法应用在 EA 交易的稳定性研究上,为此,我们需要一个概率模型来描述它们的工作。
概率性 EA 模型
在开始使用 EA 交易开始实际交易之前,赫兹量化交易软件通常会在报价历史上测试和优化它。但是为什么我们会相信,过去的交易结果会影响到未来的交易结果呢?当然,我们并不期望未来的所有交易都会形成与过去相同的顺序,尽管我们还是有假定它们会有“相似性”。让我们用概率论对这种“相似性”的直觉概念进行形式化。根据这种形式化,我们认为每个交易的结果都是某种随机变量的某种实现。在这种情况下,交易的“相似性”是通过对应的分布函数的接近来确定的。在这种形式化中,过去的交易有助于澄清未来的分配类型,并评估其可能的结果。 概率形式化使我们能够构建各种理论,让我们考虑最简单和最常用的一个。在这个理论中,由于各行业明确定义的相对利润在这个理论中,由于每个交易明确定义的相对利润k=C1/C0, 其中 C0和 C1 是交易前后的资产量。此外,相对交易利润将简单被称为利润,而 C1-C0 的差是绝对交易利润。假设所有交易的利润(无论是过去还是将来)都是相互独立的,包括均匀分布的随机值。它们的分布由 F(x) 分布函数决定,这样,赫兹量化交易软件的任务就是通过使用过去获利交易的数值来定义这个函数的类型,这是数理统计的标准问题——通过样本恢复分布函数,它的任何解决方案总是提供近似答案,让我们看看其中一些方法。
经验分布函数用作近似值,
赫兹量化交易软件使用一个简单的离散分布,其中以交易利润作为两个值中的一个。这是一个亏损概率的平均亏损,或者是一个获利概率的平均利润。
我们构造一个不是离散的,而是连续的(具有密度)近似的分布函数。为此,我们使用例如核密度估计这样的方法。
此外,我们将使用第一个选项-它是最简单和通用的。交易者对于了解函数本身并不是很感兴趣,然而,重要的是要知道什么金额表示可能的利润,从EA操作,其使用的风险水平或利润的可持续性。这些值可以通过了解分布函数来获得。 让我们在我们的例子中指定建模算法,我们的兴趣对象就是 EA 运行在未来的可能结果。它使用交易序列来定义是很明确的,每个交易都设置利润值,利润是根据上面描述的经验分布来分布的,我们应当生成大量这样的序列来计算它们每个可能的特性。生成这样的序列很简单,让我们定义,在历史中交易利润的序列为 k1, k2, ..., kn,通过使用长度 N 来生成序列, 我们将会随机(使用相等的概率 1/n) 选择 ki (有返回的样本) N 次。通常假定 N=n, 因为 N 较大时, F(x) 经验分布的近似精确度会下降。这个版本的蒙特卡洛方法有时被称为 bootstrap 方法,
让我们通过图片来解释上面的内容,它显示了几条资金曲线,它们中的每个都是根据生成的交易序列决定的。为了更方便,我使用不同的颜色对曲线做了标记,实际上,它们的数量要大得多 — 有好几万。对于它们中的每一个,我们都计算所需的参数并根据其整体性做出统计结论,很明显,这些特性中最重要的就是最终的利润。

编辑切换为居中
其他形式的概率形式化和进一步的EA操作建模也是可能的,例如,不是通过交易序列,赫兹量化交易软件可以模拟价格序列和研究EA所获得的总利润。可以根据要解决的任务来选择生成价格系列的原理,然而,这种方法需要更多的计算资源。此外,赫兹量化交易软件目前还没有提供使用随机EA的常规方法。
应用理论
赫兹量化交易软件的任务是构建特定的优化标准,它们中的每个都对应某个目标,主要的一个是一系列交易所获得的最终利润。根据利润优化已经在测试器中内建了,由于我们对未来的利润感兴趣,所以我们应该以某种方式来评估其目前偏离利润的可能程度。偏差越小,系统的利润越稳定。让我们探讨三种方法。
通过蒙特卡洛方法获得了一个可能的利润值的大样本,赫兹量化交易软件可以研究它的分布和与之相关的数量。这个利润的平均值非常重要,方差也很重要——它越小,EA的工作就越稳定,其未来结果的不确定性也就越小。我们的标准将等于平均利润与平均分散的比率,这与夏普比率类似。
另一个重要的特点是一系列交易中利润的回撤,回撤太大可能会导致存款的亏损,哪怕 EA 是获利的。为此,回撤通常会被约束。了解它会怎样影响到可能的利润很有用,该标准简单地定义为平均利润,但是条件是当超过允许的回撤水平时,交易终止。
赫兹量化交易软件将建立一个衡量利润的稳定性的持久性的贸易利润分配。从概率论的角度,这意味着交易利润在原则上,价格变化不稳定的时候的 稳定性。为此,赫兹量化交易软件将会使用类似于前瞻测试的想法。让我们把最初的交易样本分为最初和最终子样本,为了验证它们的同质性,我们可以应用统计学检验。基于这个测试,我们将创建一个优化准则。
为了演示我们的理论,我们将会使用包含在赫兹量化交易软件标准发布包中的 "Moving Average.mq5" EA 交易。我们会在它的代码中实现一些小的修改,在 EA 的开始,加上一行代码来包含我们的头文件:
#include <mcarlo.mqh>
加上代码用于在 EA 的最后获得和使用我们的优化参数:
double OnTester() { return optpr(); // 优化参数 }
基本计算都是在位于 "mcarlo.mqh" 头文件的函数中进行的,我们把它放在 "MQL5/Include/" 文件夹下。这个文件中的主函数是 optpr(),满足必要条件时,它计算由noptpr参数指定的优化标准,否则它就返回零。
double optpr() { if(noptpr<1||noptpr>NOPTPRMAX) return 0.0; double k[]; if(!setks(k)) return 0.0; if(ArraySize(k)<NDEALSMIN) return 0.0; MathSrand(GetTickCount()); switch(noptpr) { case 1: return mean_sd(k); case 2: return med_intq(k); case 3: return rmnd_abs(k); case 4: return rmnd_rel(k); case 5: return frw_wmw(k); case 6: return frw_wmw_prf(k); } return 0.0; }
setks() 函数根据交易历史计算出交易利润的数组。
bool setks(double &k[]) { if(!HistorySelect(0,TimeCurrent())) return false; uint nhd=HistoryDealsTotal(); int nk=0; ulong hdticket; double capital=TesterStatistics(STAT_INITIAL_DEPOSIT); long hdtype; double hdcommission,hdswap,hdprofit,hdprofit_full; for(uint n=0;n<nhd;++n) { hdticket=HistoryDealGetTicket(n); if(hdticket==0) continue; if(!HistoryDealGetInteger(hdticket,DEAL_TYPE,hdtype)) return false; if(hdtype!=DEAL_TYPE_BUY && hdtype!=DEAL_TYPE_SELL) continue; hdcommission=HistoryDealGetDouble(hdticket,DEAL_COMMISSION); hdswap=HistoryDealGetDouble(hdticket,DEAL_SWAP); hdprofit=HistoryDealGetDouble(hdticket,DEAL_PROFIT); if(hdcommission==0.0 && hdswap==0.0 && hdprofit==0.0) continue; ++nk; ArrayResize(k,nk,NADD); hdprofit_full=hdcommission+hdswap+hdprofit; k[nk-1]=1.0+hdprofit_full/capital; capital+=hdprofit_full; } return true; }
sample() 函数从最初的a[]序列生成随机的 b[] 序列。
void sample(double &a[],double &b[]) { int ner; double dnc; int na=ArraySize(a); for(int i=0; i<na;++i) { dnc=MathRandomUniform(0,na,ner); if(!MathIsValidNumber(dnc)) {Print("MathIsValidNumber(dnc) error ",ner); ExpertRemove();} int nc=(int)dnc; if(nc==na) nc=na-1; b[i]=a[nc]; } }
下面,我们将详细探讨上面所述的三种优化标准中的每一个,在每个例子中,我们都针对相同的时间段 - EURUSD 在2017年春/夏, 来进行优化。时段将总是1小时,而测试模式是1分钟图表的 OHLC。全都使用自定义优化中的遗传算法,因为我们的任务是证明理论而不是准备实际交易的EA,这种简单化的方法似乎是很自然的。
利润鲁棒性对随机散射
假设我们有一个产生最终利润的样本,我们可以借助数理统计的方法进行研究。面的图像显示了一个带有虚线标记的选择中值的直方图。

编辑切换为居中