English Русский Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
将您的线性交易系统提升为幂交易系统

将您的线性交易系统提升为幂交易系统

MetaTrader 5交易系统 |
3 159 14
laplacianlab
[删除]

简介

今天的文章为中级 MQL5 编程人员讲解如何通过轻松实施所谓的幂的技术从他们的线性交易系统(固定手数)中获利更多。本文中使用的泛称取幂是指那些使市场中下达的仓位的规模或数量与其风险相适应的货币管理模型。这是因为结果资产净值曲线呈抛物线形式,以几何级数或指数增长。术语“线性”也用于本文的上下文中,是一个介于数学和编程之间的术语。具体而言,我们将实施一个由 Ralph Vince 开发的固定分数仓位大小的实际 MQL5 变体。

图 1. 数学抛物线


图 1. 数学抛物线

现在,让我们快速回顾一下资金管理模型,看看我们可以如何实现 Ralph Vince 的固定分数仓位规模的变体。准备好了吗?不要错过从您的交易策略获利更多的机会!

1. 什么是资金管理模型?

一言以蔽之,资金管理模型是概念框架,在此框架下您作出与您的仓位规模、止损的使用以及预付款计算和交易成本相关的决策。网络上有大量的资金管理模型可用!如果您愿意,您可以搜索固定手数、固定分数、固定比率、Kelly 的百分比或实际成本加深您对这些经典框架的了解。正如我说的,本文仅涉及固定分数的一种变体。


1.2. 固定分数

本资金管理模型背后的理念是根据与操作相关的估计风险对操作进行分级。风险是每项交易净额的相同部分。

固定分数仓位规模中合约数量的方程如下:



N = f * Equity / Trade Risk

N 是合约数量,f 是固定分数(介于 0 和 1 之间的数),Equity 是账户资产净值的当前值,Trade Risk 是计算合约数量的每份合约的风险。请阅读 Michael R. Bryant 的《固定分数仓位规模》一文,以更深入地了解此模型。

固定分数模型的一个有趣属性是,由于操作的规模保持与账户的净余额成比例,从理论上说不可能损失所有的资金。破产的风险为零。从另一方面来说,由于风险资金的百分比较低,连赢或连输操作不会对利润曲线造成显著影响。

2. 将固定分数添加至您的交易系统


2.1. 获得您的线性交易系统

当然,首先您需要一个线性交易系统以体验低风险指数幂!可以这么说,这个系统将作为幂底。但我所指的线性系统是经证明在某个时间区间内是赢家且其资产净值曲线看上去像一条直线的交易系统。例如,HawaiianTsunamiSurfer 就是代码库中提供的所谓的线性交易系统。其资产净值曲线在从 2012 年 1 月到 2012 年 3 月的时间区间内看起来像一条直线。

图 2. HawaiianTsunamiSurfer 从 2012 年 1 月到 2012 年 3 月的资产净值曲线

图 2. HawaiianTsunamiSurfer 从 2012 年 1 月到 2012 年 3 月的资产净值曲线

本文的目的不是从头开发一个线性交易系统,而是为您提供必要的工具,以便您可以从您的系统中获益更多。所以从现在开始,我假设您已经在面向对象范式下开发了一个类似于这个系统的交易系统。在这种情况下,您应添加我在下文中说明的面向对象块。

2.2. 使用 MQL5 的核心类 - CEvolution - 将您的系统提升为幂级

所以,我们再次采取面向对象的方法来编写我们的 EA 的代码。我建议您首先阅读《另一个 MQL5 OOP 类》《建立自动新闻交易者》这两篇文章,获得以此面向对象的方式工作的技术基础。如果您已经完成这一步,记住在那些文章中讨论的设计包含了名为 CEvolution 的非常重要的元素。这允许我们对一些重要的临时信息保持追踪,例如自动交易在给定时刻的状态、执行的操作的历史数据等。

这一次,我们将在 CEvolution 中编写管理我们的资金所需的逻辑的代码。由于风险固定分数与资产净值保持比例,在此我们都同意它不是恒定的而是可变的,此逻辑必须在 CEvolution 中编写代码。或者简单地说,由于资产净值曲线的斜率随时间而变化,所有这些问题必须在 CEvolution 中实现。这是我们面向对象设计的抽象概念。将下列面向对象类与您的面向对象风格的交易系统集成起来的工作留给读者作为练习。

CEvolution.mqh

//+------------------------------------------------------------------+
//|                                                   CEvolution.mqh |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+
#include <Mine\Enums.mqh>
//+------------------------------------------------------------------+
//| CEvolution Class                                                 |
//+------------------------------------------------------------------+
class CEvolution
  {
protected:
   ENUM_STATUS_EA                   m_status;            // The current EA's status
   ENUM_EXP_EQUITY_CURVE_LEVEL      m_expEquityLevel;    // The current exponential equity level
   double                           m_originalEquity;    // The original equity value
   double                           m_lotSize;           // The current lot size

public:
   //--- Constructor and destructor methods
                                    CEvolution(ENUM_STATUS_EA status,ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level);
                                    ~CEvolution(void);
   //--- Getter methods
   ENUM_STATUS_EA                   GetStatus(void);
   ENUM_EXP_EQUITY_CURVE_LEVEL      GetExpEquityLevel(void);
   double                           GetOriginalEquity(void);
   double                           GetLotSize(void);
   //--- Setter methods
   void                             SetStatus(ENUM_STATUS_EA status);
   void                             SetExpEquityLevel(ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level);
   void                             SetOriginalEquity(double equity);
   void                             SetLotSize(double size);
   //--- CEvolution specific methods
   double                           CalcEquityGrowth(double currentEquity);
   void                             RefreshExpEquityLevel(double currentEquity);
   void                             RefreshLotSize();
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CEvolution::CEvolution(ENUM_STATUS_EA status,ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level)
  {
   m_status=status;
   m_expEquityLevel=exp_equity_level;
   RefreshLotSize();
   m_originalEquity=AccountInfoDouble(ACCOUNT_EQUITY);
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CEvolution::~CEvolution(void)
  {
  }
//+------------------------------------------------------------------+
//| GetStatus                                                        |
//+------------------------------------------------------------------+
ENUM_STATUS_EA CEvolution::GetStatus(void)
  {
   return m_status;
  }
//+------------------------------------------------------------------+
//| GetExpEquityLevel                                                |
//+------------------------------------------------------------------+
ENUM_EXP_EQUITY_CURVE_LEVEL CEvolution::GetExpEquityLevel(void)
  {
   return m_expEquityLevel;
  }
//+------------------------------------------------------------------+
//| GetEquity                                                        |
//+------------------------------------------------------------------+
double CEvolution::GetOriginalEquity(void)
  {
   return m_originalEquity;
  }
//+------------------------------------------------------------------+
//| GetLotSize                                                       |
//+------------------------------------------------------------------+
double CEvolution::GetLotSize(void)
  {
   return m_lotSize;
  }
//+------------------------------------------------------------------+
//| SetStatus                                                        |
//+------------------------------------------------------------------+
void CEvolution::SetStatus(ENUM_STATUS_EA status)
  {
   m_status=status;
  }
//+------------------------------------------------------------------+
//| SetExpEquityLevel                                                |
//+------------------------------------------------------------------+
void CEvolution::SetExpEquityLevel(ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level)
  {
   m_expEquityLevel=exp_equity_level;
  }
//+------------------------------------------------------------------+
//| SetEquity                                                        |
//+------------------------------------------------------------------+
void CEvolution::SetOriginalEquity(double equity)
  {
   m_originalEquity=equity;
  }
//+------------------------------------------------------------------+
//| SetLotSize                                                       |
//+------------------------------------------------------------------+
void CEvolution::SetLotSize(double lot_size)
  {
   m_lotSize=lot_size;
  }
//+------------------------------------------------------------------+
//| CalcEquityGrowth                                                 |
//+------------------------------------------------------------------+
double CEvolution::CalcEquityGrowth(double currentEquity)
  {
   return NormalizeDouble(currentEquity * 100 / m_originalEquity - 100,2);
  }
//+------------------------------------------------------------------+
//| RefreshExpEquityLevel                                            |
//+------------------------------------------------------------------+
void CEvolution::RefreshExpEquityLevel(double currentEquity)
  {
   double growth = CalcEquityGrowth(currentEquity);
   //--- is the current equity less than 10% of the original amount?
   if(growth <= 10)
   {
      SetExpEquityLevel(LEVEL_ONE);
   }
   //--- is the current equity more than 10% of the original amount and less than 20%?
   else if(growth > 10 && growth <= 20)
   {
      SetExpEquityLevel(LEVEL_TWO);
   }
   //--- is the current equity more than 20% of the original amount and less than 30%?
   else if(growth > 20 && growth <= 30)
   {
      SetExpEquityLevel(LEVEL_THREE);
   }
   //--- is the current equity more than 30% of the original amount and less than 40%?
   else if(growth > 30 && growth <= 40)
   {
      SetExpEquityLevel(LEVEL_FOUR);
   }
   //--- is the current equity more than 40% of the original amount and less than 50%?
   else if(growth > 40 && growth <= 50)
   {
      SetExpEquityLevel(LEVEL_FIVE);
   }
   //--- is the current equity more than 50% of the original amount and less than 60%?
   else if(growth > 50 && growth <= 60)
   {
      SetExpEquityLevel(LEVEL_SEVEN);
   }
   //--- is the current equity more than 60% of the original amount and less than 70%?   
   else if(growth > 60 && growth <= 70)
   {
      SetExpEquityLevel(LEVEL_EIGHT);
   }
   //--- is the current equity more than 70% of the original amount and less than 80%?   
   else if(growth > 70 && growth <= 80)
   {
      SetExpEquityLevel(LEVEL_NINE);
   }
   //--- is the current equity more than 90% of the original amount?
   else if(growth > 90)
   {
      SetExpEquityLevel(LEVEL_TEN);
   }
  }
//+------------------------------------------------------------------+
//| RefreshLotSize                                                   |
//+------------------------------------------------------------------+
void CEvolution::RefreshLotSize()
  {
   switch(m_expEquityLevel)
   {
      case LEVEL_ONE:
         SetLotSize(0.01);
         break;
         
      case LEVEL_TWO:
         SetLotSize(0.02);
         break;
         
      case LEVEL_THREE:
         SetLotSize(0.03);
         break;
         
      case LEVEL_FOUR:
         SetLotSize(0.04);
         break;
         
      case LEVEL_FIVE:
         SetLotSize(0.05);
         break;
         
      case LEVEL_SIX:
         SetLotSize(0.06);
         break;
         
      case LEVEL_SEVEN:
         SetLotSize(0.07);
         break;

      case LEVEL_EIGHT:
         SetLotSize(0.08);
         break;
         
      case LEVEL_NINE:
         SetLotSize(0.09);
         break;
         
      case LEVEL_TEN:
         SetLotSize(0.1);
         break;
   }
  }
//+------------------------------------------------------------------+

现在,让我们对这个类的一些重要部分进行注释!

当创建“EA 交易”时,原始资产净值曲线的值存储在 m_originalEquity 中:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CEvolution::CEvolution(ENUM_STATUS_EA status,ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level)
  {
   m_status=status;
   m_expEquityLevel=exp_equity_level;
   RefreshLotSize();
   m_originalEquity=AccountInfoDouble(ACCOUNT_EQUITY);
  }

方法 CEvolution::CalcEquityGrowth 用于计算资产净值曲线的增长,这始终是相对于其原始值而言:

//+------------------------------------------------------------------+
//| CalcEquityGrowth                                                 |
//+------------------------------------------------------------------+
double CEvolution::CalcEquityGrowth(double currentEquity)
  {
   return NormalizeDouble(currentEquity * 100 / m_originalEquity - 100,2);
  }

最后,CEvolution::RefreshExpEquityLevel 用于刷新每一价格变动的资产净值水平(观察它是如何完全取决于资产净值增长的),CEvolution::RefreshLotSize 用于刷新每一价格变动的手数。这是因为您应该以下列方式在您的 EA 的 OnTick 方法中刷新该信息:

GetEvolution().RefreshExpEquityLevel(AccountInfoDouble(ACCOUNT_EQUITY));
GetEvolution().RefreshLotSize();

顺便提一下,此解决方案要求使用下列自定义 MQL5 枚举:

//+------------------------------------------------------------------+
//| Exponential equity curve level enumeration                       |
//+------------------------------------------------------------------+
enum ENUM_EXP_EQUITY_CURVE_LEVEL
  {
   LEVEL_ONE,
   LEVEL_TWO,
   LEVEL_THREE,
   LEVEL_FOUR,
   LEVEL_FIVE,
   LEVEL_SIX,
   LEVEL_SEVEN,
   LEVEL_EIGHT,
   LEVEL_NINE,
   LEVEL_TEN
  };
我们说这个实现是固定分数的变体,是因为它的确引进了一些特异性。例如,资产净值曲线在达到所谓的水平十之前将呈指数增长,之后系统变成线性。然而,CEvolution 保留了恒定与资产净值曲线成比例增大仓位规模的基本理念。

2.3. 作出您的固定分数决策

综上所述,您已经可以根据您的自动交易的当前状态作出资金管理决策。

在您的 EA 的 OnTick 方法中:

switch(GetEvolution().GetStatus())
     {
      case BUY:

         tp = ask + m_takeProfit * _Point;
         sl = bid - m_stopLoss * _Point;

         GetTrade().PositionOpen(GetBrain().GetSymbol(),ORDER_TYPE_BUY,m_evolution.GetLotSize(),ask,sl,tp);
         
         break;

      case SELL:

         sl = ask + m_takeProfit * _Point;
         tp = bid - m_stopLoss * _Point;

         GetTrade().PositionOpen(GetBrain().GetSymbol(),ORDER_TYPE_SELL,m_evolution.GetLotSize(),bid,sl,tp);
         
         break;

      case DO_NOTHING:

         // Nothing...

         break;
     }

我将新的指数化系统重命名为 ExponentialHawaiian。

3. 回测您的指数化系统

完成上文中说明的面向对象逻辑的添加后,不要忘记对您的系统运行测试!现在我来回测 ExponentialHawaiian - HawaiianTsunamiSurfer 的固定分数变体:

图 3. ExponentialHawaiian 从 2012 年 1 月到 2012 年 3 月的资产净值曲线

图 3. ExponentialHawaiian 从 2012 年 1 月到 2012 年 3 月的资产净值曲线

上面的曲线将保持指数化,而下面的系统保持线性。当这个条件不再为真时,系统变得不稳定,从理论上存在破产的风险。

总结

今天我们学习了如何通过将我们实施固定手数资金管理模型的线性系统升级至幂系统来获得更多利润。

首先我们展示了几个经典的资金管理模型(固定手数、固定分数、固定比率、Kelly 的百分比、实际成本)并决定专注于固定分数 - 一个操作规模保持与账户净余额成比例的简单模型。最后,我们采取了在一段时间内显示线性结果的交易系统,我们以 MQL5 实施了固定分数的变体,并显示了 MetaTrader 的策略测试程序启动的结果。

我们再次使用面向对象方法编写我们的“EA 交易”。我强烈建议您首先阅读《另一个 MQL5 OOP 类》《建立自动新闻交易者》这两篇文章,获得以此面向对象的方式工作的技术基础。

本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/734

附加的文件 |
cevolution.mqh (8.35 KB)
最近评论 | 前往讨论 (14)
Maxim Khrolenko
Maxim Khrolenko | 21 11月 2013 在 12:28
在我看来,通过 3 个月的测试结果来显示创新的优势并不是一个好主意。如果我将其与 10 年期进行比较。
Yury Reshetov
Yury Reshetov | 21 11月 2013 在 13:31
laplacianlab:

好吧, 你是个好读者,让我们来 深入探讨一下这个话题! 我要你思考。

认为交易 就像数学,然而 我的文章 为你 打开了一扇门 ,让你 的批判能力得到 锻炼,就像你现在所做的一样。 在我看来, 交易 需要 这样做 任何 系统 提升 到权力的高度并使自己 成为百万富翁,这实际上是荒谬的 那样的话, 我们都会成为 富翁。

有趣的是,基础理论仍然是正确的。 这就是为什么我说"一旦你在系统中添加了上面解释的 OO 逻辑,不要忘记运行你的测试!现在,我正在回测ExponentialHawaiian,即 HawaiianTsunamiSurfer的固定分数变体 "。

上面这句话是正确的。因此 ,严格来说, 让我说,也许 你做了一个 错误的 逻辑推理。我不希望读者认为,只要把任何线性交易系统提升到权力的高度,他/她就会成为百万富翁。我鼓励你将 CEvolution 与你的系统结合起来,观察自己的结果。这就是交易!我认为。

有趣的是,如果你研究过爱德华-索普(Edward Thorp),而不是文斯,你就会知道,固定分数不一定适合所有的策略,因为在某些情况下,你需要大量的交易,才会得到更好的结果。

见:Edward O. Thorp.21点、体育、博彩和股市中的凯利标准

在此阅读更多内容: 4.长跑:凯利策略何时 "称霸"?

任何策略都不能使用固定的分数。因为它并不总是比其他管理资本和风险的策略带来更好的结果。


E.索普是一位优秀的数学家、赌徒和经验丰富的交易者。他在实践中获得了成功。

R.Vince - 理论家,不是 实践家 他在书中不正确地抄袭别人的观点,并因此收取版税。

文斯的追随者经常犯错误,这些错误在交易实践中早已有之,但在文斯的书中却只字未提。他们试图把数学方法用到不能用的地方。

我扔掉了文斯的书,因为它们有很多不准确的地方,而且几乎没有实际用途。

Yury Reshetov
Yury Reshetov | 21 11月 2013 在 14:30
paladin800:
在我看来,通过 3 个月的测试结果来显示创新的优势并不是一个好主意。如果要比较,我会用 10 年的时间来比较。
你认为创新的 "优势 "在哪里?用什么指标来衡量?
GaryKa
GaryKa | 21 11月 2013 在 16:48

用非线性函数(指数,简单明了)对价格图表(甚至随机走势)进行缩放,就能在一两次内做出 "圣杯 "TS。这种缩放最终归结为头寸规模的管理。但整个问题在于市场是离散的:你有最小的手数,也有最小的价格波动(点数)。最终,在这些离散的部分中,所有非线性都会退化为线性。

我说的是在不考虑佣金和点差的情况下--对于长期投资者来说,这是一个抽象的价格线))。

GaryKa
GaryKa | 22 11月 2013 在 16:48
Ha ))) 找到了获得非线性的方法。用不相等的权重因子进行合成。自言自语 )))
技术指标和数字滤波器 技术指标和数字滤波器
在本文中,技术指标被视为数字滤波器。本文对数字滤波器的操作原理和基本特性进行了说明。同时,本文还涉及在 MetaTrader 5 终端中接收滤波器内核以及与建立一个频谱分析程序一文中提出的现成频谱分析程序集成等实用方法。本文将典型数字滤波器的脉冲和频谱特性用作示例。
通过有用的技术组合让您的 MQL5 客户惊叹! 通过有用的技术组合让您的 MQL5 客户惊叹!
得益于 MQL5 为编程人员提供的一套非常完整的函数集和面向对象 API,他们可以在 MetaTrader 环境中大展身手。然而,Web 技术如今是用途极为广泛的工具,可以在一些情形中提供帮助:当您需要完成一些非常具体的工作;希望用一些不同的东西给您的客户留下深刻印象;或仅仅是您没有足够的时间来掌握 MT5 标准库的特定部分。今天的练习引导您完成有关如何在创建令人惊叹的技术组合的同时,管理您的开发时间的实例。
扩展 MQL5 标准库和重用代码 扩展 MQL5 标准库和重用代码
作为一名开发人员,MQL5 标准库让您的工作变得更加容易。然而,它无法实现世界上所有开发人员的全部需求,所以,如果您觉得您需要更多的自定义程序,您可以对标准库进行进一步的扩展。本文指导您完成将 MetaQuotes 的峰谷技术指标集成至标准库。我们从 MetaQuotes 的设计理念获得启发以实现我们的目标。
MQL5 向导:如何教导 EA 以任意价格建立挂单 MQL5 向导:如何教导 EA 以任意价格建立挂单
本文讲述允许您以距当前价格的任意距离设置挂单的功能实现的交易信号模块代码的修改方法:它可以是上一个柱的收盘价或开盘价,或者是移动平均线的值。有很多的选择。重要的是,您可以为挂单设置任意的开盘价。本文对于使用挂单交易的交易人员而言会有所帮助。