市场及其全球格局的物理学

2021年2月12日,16:32
叶夫根尼·伊林(Evgeniy Ilin)
0
5 401

介绍

在本文中,我们将尝试了解如何将市场物理学用于自动交易。数学语言意味着从抽象性和不确定性到预测的过渡。这样可以使用明确的公式或标准进行操作,而不是使用一些近似和模糊的值来进行操作,以提高所创建系统的质量。我不会发明任何理论或模式,而只会使用已知的事实,并将这些事实逐步转化为数学分析的语言。没有数学,市场物理学是不可能的,因为我们产生的信号是数学实质。许多人试图创建各种理论和公式,而没有进行任何统计分析或使用非常有限的统计数据,这通常不足以得出如此大胆的结论。单独实践是真理的标准。首先,我将尝试进行一些反思,然后,基于这些反思,我将创建一个EA交易。随后将进行EA测试。


价格及其提供的东西

任何市场环境都意味着存在各种产品。在货币市场上,产品就是货币。货币是指拥有某些产品或信息的权利,该权利被确定为全世界的基准。例如,考虑EURUSD对​​及其图表的当前值。当前图表值将表示USD / EUR = CurrentPrice。或者: 美元=  欧元*目前的价格, 这表示一欧元中包含的美元数量。换句话说,该值表示每种货币权重的比率,而当然,假定每种货币存在某种通用的兑换等价物,即某种通用商品或其他某种东西。价格是在订单簿中形成的,而订单簿的动态决定了价格变动。应当永远记住,我们将永远无法考虑到价格形成的所有因素。例如,FORTS与FOREX相关联,并且两个市场相互影响。我不是这方面的专家,但是我能够理解所有内容都是绑定的,并且数据通道越多越好。在我看来,最好不要深入研究这些细节,而要专注于能够改变价格的简单事物。

任何依赖关系都可以表示为许多变量的函数,就像任何引号一样。最初,价格为:

  • P = P(t)

换句话说,价格是时间的函数。无法为每个货币对或任何其他工具可靠地建立功能的形式,因为这将花费无限的时间。但是此演示文稿没有给我们任何帮助。但是,价格具有双重性质,因为它既具有可预测的成分又具有随机成分。可预测的部分不是函数本身,而是其一阶导数。用某些术语来表示此功能是没有意义的,因为这没有交易的目的。但是,如果考虑它的一阶导数,则有以下内容:

  • P'(t)= Pa'(t)+ Pu'(t)

在这里,第一个术语反映了可以使用数学分析以某种方式分析的部分,第二个则是不可预测的部分。根据这个公式,可以说不可能以100%的精度预测运动的大小和方向。由于我们无法确定最后一个术语,因此无需考虑最后一个术语。但是我们可以确定第一个。考虑到值函数是离散的,并且我们不能应用微分运算,因此可以假定该术语可以用不同的形式表示。但是,我们可以取时间“ st”的平均导数。当应用于价格时,这将是一个柱线的持续时间;当应用于刻度时,它是两个刻度之间的最短时间。

  • PaM(t)=(Pa(t)-Pa(t-英石 ))/ st-固定时间段内的平均价格变动(时间导数)
  • Ma(t)= Ma(P(t),P(t-st) + ... + P(t-N*st), D(t),D(t-st) + ... + D(t-N * st),U [1](),U [2](t)+ ... + U[N](t) )
  • P(t [i])-旧价格值(条形或报价数据)
  • D(t [i])-其他货币对上的旧价格值
  • U [i](t)-其他影响市场的未知或已知值
  • 垫) -对数学的期望 给定时间点的PaM(t)值 

换句话说,我们假设价格的可预测部分可能取决于先前的柱线或价格变动,以及其他货币对的价格数据,其他交易所和世界事件的数据。但是,应该理解,即使这部分价格也无法100%准确地预测,但我们只能计算其某些特征。这样的特征只能是概率或随机变量的参数,例如数学期望,方差,标准差和概率论的其他数量。以数学期望进行操作足以使交易获利。经过花费时间和仔细的思考,我们可以得出结论,不仅可以使用此逻辑来分析市场。问题是价格的可预测部分是根据市场参与者的活动而发展的。除了市场参与者自己创造的因素之外,我们可以丢弃各种市场参数。当然,所有这些都会导致我们分析方法的可靠性下降,但这极大地简化了模型。在此,“ st”值越小,我们的公式对市场的描述就越准确。

  • VMa(t)= VMa(P(t),P(t-st)+ ... + P(t-N * st))
  • VMa(t)= VBuy(t)-VSell(t)
  • VMa(t)-总体积
  • VBuy(t)-未结购买订单的数量
  • VSell(t)-未平仓订单的数量

上面的功能描述了当前所有未平仓交易头寸的数量差异。这些位置中的一部分相互补偿,而其余位置是独立的。由于仓位是开放的,它们象征着一段时间后会关闭的承诺。我们都知道,购买使价格上涨,而销售使价格下跌。知道价格走势的唯一方法是测量未结头寸的数量并估计这些头寸的方向,仅考虑未结头寸的订单。

市场的波动本质实际上与这个简单的事实有关。这只是持仓量波动或多头和空头行为的更一般过程的一种特殊情况。

在处理条形图时,还可以考虑以下事实:条形图中有4个价格,这可以为我们提供更好的公式。更多数据意味着更准确的分析,这就是为什么考虑所有价格数据很重要的原因。但是,我不喜欢计数每个刻度,因为这会使算法减慢十倍。此外,不同的经纪人的报价数据可能会不同。相反,大多数经纪人的开盘价和收盘价几乎相同。让我们修改体积函数以考虑所有价格数据:

  • VMa(t)= VMa(O(t),O(t-st)+ ... + O(tN * st)+ C(t),C(t-st)+ C(tN * st),H (t),H(t-st)... H(tN * st),L(t),L(t-st)... L(tN * st))

我们可以在此函数中添加更多变量,例如时间,一周中的几天,几个月和几周,但这将产生许多与特定市场区域相关的函数,而我们的目的是确定一般的市场物理学。我们将知道它不会被破坏,因此只要有市场就可以使用。该公式的另一个优点是它具有多种货币的性质。

实际上,使用这种表示类型是没有意义的,因为我们需要确切地知道如何以及基于什么数据来构建此功能。我们不能只是编写此函数的形式并确定依赖关系。但是这些表述可以帮助我们初步了解如何分析以及如何继续以下假设。任何逻辑条件集最终都可以表示为这种功能。相反,函数本身可以变成一组条件。我们使用哪种形式都没有关系。了解它只是重要的。任何算法都可以简化为某个公式。有时,将信号描述为条件或条件系统要比构建超复杂函数更容易。另一个大问题是如何构建这样的功能。

在真实的交易系统中,我们无法一次分析整个历史,而只能分析固定的时间段。有4种可能的分析方法。我将为它们创建名称并解释:

  • 公式(指标或其功能)
  • 模拟
  • 普通数学
  • 机器学习的类型

第一个选项假设我们使用一个特定值或一组值。一个例子是指标或我们自己的公式。这种方法的优点是可以在MetaTrader 4/5终端中使用大型工具包。此外,有许多基于流行市场理论的指标,可以在市场和网络上获得。这种方法的缺点是,在大多数情况下,我们无法根据指标的作用来理解。即使我们理解,这种理解也没有任何价值。

在第二个选项中,我们不使用我们不了解或可能没有用的数据。相反,我们可以尝试模拟市场中的订单,因此,我们将知道我们的系统将能够在一定程度上描述一个方向上有多少个头寸,而另一个方向上有多少个头寸。这些信息可以产生必要的预测,从而可以在全球范围内更好地描述市场。这是机器学习的唯一替代方法。

数学是指对一些基本定律的理解或对某些数学原理的了解,无论当前的市场形势如何,都可以利用任何报价。事实是,包括离散功能在内的任何功能都具有可以利用的某些特征。当然,这里我们假设依赖关系不是混乱的(在我们的例子中,外汇不是混乱的,因此可以利用任何报价)。在下一篇文章中,我们将分析一个几乎每个人都知道的这样的原理。但是要知道并能够使用是两件事。这种方法的优势在于,如果我们成功构建了一个成功的系统,则无需担心将来的系统性能。 

第四种方法是最先进的方法,因为机器学习可以充分利用任何数据。您拥有的计算能力越强,分析的质量就越高。这种方法的缺点是它无助于了解市场物理。优点是方法简单,结果质量最高,花费的时间最少。但是这种方法不适用于本文。


关于图案

日常交易意味着很多术语,每个术语具有不同的重要性级别。尽管并非所有交易者都能理解其真实目的,但还是经常使用某些术语。这些术语之一是模式。我将尝试用数学语言解释它。模式始终与特定的时间段以及特定的货币对和图表周期链接。有些模式很强。这种模式可以是多币种的,也可以是全球性的。一个理想的模式是圣杯。有一些语句可以应用于任何模式:

  • 表示模式的公式或条件集的存在
  • 策略测试器中的最低测试值或模拟或真实帐户中的性能值
  • 根据所有货币对和图表周期的表现对模式进行分类
  • 发现模式的历史时期
  • 未来的时间间隔,在此时间间隔内模式仍可运行
  • 未来的第二个时间段,在第一个时间段之后,在此期间原始模式会保留某些参数或将其取反

如果仔细阅读每个属性,便可以理解,模式是公式或一组条件,可以最准确地描述选定间隔的价格走势。模式可能是随机的,尤其是在周期太短或相关系统产生过分乐观的值的情况下。了解短时间内测试系统时,发现全局模式的可能性趋于零,这一点非常重要。这与样本量有关。样本越小,结果的随机性越高。 

我们已经确定了一种模式。但是如何有效利用模式呢?这完全取决于如何找到此模式及其质量。如果我们不考虑利用计算能力的分析方法,那么我们将进行分析。在我看来,分析无法与任何类型的机器分析竞争-甚至一个好的分析团队也无法处理可以由一台机器处理的数据。无论如何,寻找全局模式的过程需要计算能力。好吧,除了您用肉眼看到明显的事物并了解其物理原理的情况。


编写最简单的位置模拟器

为了尝试找到全局模式,开发一个可以描述市场参与者情绪的EA交易会很有趣。为此,我决定尝试创建一个市场地位模拟器。将模拟靠近市场边缘的柱线中的头寸。有必要假设市场参与者不同,他们的订单权重也不同。同时,这应该以简单的形式呈现。如果一个简单的原型显示出利润,那么可以进一步使用其原理。

该逻辑将有条件地分为3个单独的仿真以及它们的任何可能的混合组合:

  • 模拟止损单
  • 模拟限价单
  • 模拟市场订单
  • 任何可能的组合

以下逻辑将用于下订单:

订单网格逻辑

这些网格是每个新栏的位置,旨在模拟市场参与者的某些部分的情绪。旧订单网格的状态将根据图表上显示的新条进行更新。这种方法不是很准确,但是逐个刻度的模拟将导致无休止的计算。而且,我不太相信刻度线。

相对体积的分布有两种类型,即衰减量和均匀量,但仅适用于止损和限价订单。市场订单分布均匀。如果从透视的角度来看,也有可能扩大发行的类型。这是插图:

相对体积填充类型

在此,表示订单的线的长度与相同订单的数量成正比。我认为这样的插图对每个人都是简单易懂的。

在这种情况下,可以使用面向对象的方法来完成所有操作。让我们开始描述编号列表:

enum CLOSE_MODE// how to close orders
   {
   CLOSE_FAST,// fast
   CLOSE_QUALITY// wait for an opposite signal
   };

enum WORK_MODE// operation mode
   {
   MODE_SIMPLE,// slow mode
   MODE_FAST// fast mode
   };

enum ENUM_GRID_WEIGHT//weight fill type for limit and stop orders
   {
   WEIGHT_DECREASE,// with attenuation if moving from the price
   WEIGHT_SAME// the same for the entire grid
   };

enum ENUM_STATUS_ORDER// statuses of orders or positions
   {
   STATUS_VIRTUAL,// stop or limit order
   STATUS_MARKET,// market order
   STATUS_ABORTED// canceled stop or limit order
   };

模拟器将以两种模式工作,即慢速和快速。慢速模式主要用于开始分析。在开始分析中,在最接近市场烛台的第一个“ n”中执行计算。在快速模式下,仅在新出现的烛台上执行计算。但是,简单的方法还不够。需要附加功能来提高算法速度。 EA交易初始化时执行了大量计算。但是,我们只需要在每个烛台上更新一个新烛台的模拟即可。限价单和止损单有两种类型的交易量分配,具体取决于与当前市场价格的距离,每条价格为Open [i]。这是因为在每个柱上打开了止损和限价单网格,具有不同的分布和权重。一段时间后,止损和限价订单变成市场订单。如果价格在指定时间内未达到要求的价格,则止损单和限价单将被取消。

让我们开始构建从简单到复杂的仿真,然后逐步将所有内容组合在一起。首先,定义什么是订单:

英石 ruct Order// structure symbolizing a player's order
   {
   public:
   double WantedPrice;// desired open price
   int BarsExpirationOpen;// If the order remains for certain number of bars, the player can't wait any more and cancels the order
   int BarsExpirationClose;//If this is a market order and the player does not want to wait, he closes the position
   double UpPriceToClose;//The total upward price movement at which the player closes the order (points)
   double LowPriceToClose;//The total downward price movement at which the player closes the order 
   double VolumeAlpha;// current volume equivalent [0...1]
   double VolumeStart;// starting volume equivalent [0...1]
   int IndexMarket;// the index of the bar on which the virtual market turned into market
   ENUM_STATUS_ORDER Status;// order status
   Order(ENUM_STATUS_ORDER S)// constructor that creates a certain order
      {
      Status=S;
      }
   };

参数不多,每个参数对于通用算法都很重要。许多字段适用于任何订单,而某些字段仅适用于限价或止损订单。例如,期望价格是市场订单的开盘价格,而恰好是限价和止损订单的期望价格。

最高和最低收盘价充当止损价位。同时,我们将假设网格订单不是一个订单,并且该订单包含一整串订单,而它们只是合并为一个订单,该订单以一定的价格以一定的数量打开。起始数量和当前数量的变量告诉我们订单在特定柱线的特定级别有多重要。

起始数量是下订单时的数量。当前数量是事件进一步发展的数量。重要的是买卖订单数量的比率,而不是某些订单的利润。基于这些考虑,将产生交易信号。当然,我们可以提出其他信号,但这需要一些其他考虑。另请注意,定单在达到一定水平时不会平仓,而是在每个柱线处逐渐平仓,以尽可能模拟事件的真实发展。

接下来,我们需要为每个条定义存储空间。酒吧将存储在此酒吧打开的订单:

class OrderBox// Order box of a specific bar
   {
   public:
   Order BuyStopOrders[];
   Order BuyLimitOrders[];
   Order BuyMarketOrders[];
   Order SellStopOrders[];
   Order SellLimitOrders[];
   Order SellMarketOrders[];
   
   OrderBox(int OrdersToOneBar)
      {
      ArrayResize(BuyStopOrders,OrdersToOneBar);
      ArrayResize(BuyLimitOrders,OrdersToOneBar);
      ArrayResize(BuyMarketOrders,OrdersToOneBar);
      ArrayResize(SellStopOrders,OrdersToOneBar);
      ArrayResize(SellLimitOrders,OrdersToOneBar);
      ArrayResize(SellMarketOrders,OrdersToOneBar);      
      for ( int i=0; i<ArraySize(BuyStopOrders); i++ )// Set types for all orders
         {
         BuyStopOrders[i]=Order(STATUS_VIRTUAL);
         BuyLimitOrders[i]=Order(STATUS_VIRTUAL);
         BuyMarketOrders[i]=Order(STATUS_MARKET);
         SellStopOrders[i]=Order(STATUS_VIRTUAL);
         SellLimitOrders[i]=Order(STATUS_VIRTUAL);
         SellMarketOrders[i]=Order(STATUS_MARKET);         
         }
      }
   };

这里的一切都很简单。六种类型的订单,用数组描述。这样做是为了避免混淆。该类不会以其纯粹的形式使用,而只是建筑中的一块砖。

接下来,将所有条的公共存储定义为一个对象,稍后将从该对象执行继承。这里的技术非常简单。

class BarBox// Storage for all orders
   {
   protected:
   OrderBox BarOrders[];
   
   BarBox(int OrdersToOneBar,int BarsTotal)
      {
      ArrayResize(BarOrders,BarsTotal);
      for ( int i=0; i<ArraySize(BarOrders); i++ )// Set types for all orders
         {
         BarOrders[i]=OrderBox(OrdersToOneBar);
         }
      }   
   };

这只是具有条形数据(订单)的存储。到目前为止,一切都非常简单。此外,事情变得更加复杂。

在确定了方便的订单数据存储之后,我们需要确定如何创建订单以及如何根据规则创建订单,确定特定订单类型的重要性等。为此,我创建了以下类:

class PositionGenerator:public BarBox// Inherit class from the box to avoid the need to include it as an internal member and to avoid multiple references
   {
   protected:
   double VolumeAlphaStop;// importance of volumes of STOP orders
   double VolumeAlphaLimit;// importance of volumes of LIMIT orders
   double VolumeAlphaMarket;// importance of volumes of MARKET orders
   double HalfCorridorLimitStop;// step of the corridor of Limit and Stop orders in points
   int ExpirationOpenLimit;// after how many bars the volumes of the grid of limit orders for opening will completely attenuate
   int ExpirationOpenStop;// after how many bars the volumes of the grid of stop orders for opening will completely attenuate
   int ExpirationClose;// after how many bars the volumes of orders for closing will completely attenuate
   int ProfitPointsCorridorPart;// half corridor size for the profit of all orders
   int LossPointsCorridorPart;// half corridor size for the loss of all orders
   int OrdersToOneBar;// orders of one type per 1 bar
   ENUM_GRID_WEIGHT WeightStopLimitFillingType;
   
   PositionGenerator( ENUM_GRID_WEIGHT WeightStopLimitFillingType0
                     ,int HalfCorridorLimitStop0,int OrdersToOneBar0,int BarsTotal0
                     ,int ExpirationOpenLimit0,int ExpirationOpenStop0
                     ,int ExpirationClose0
                     ,int ProfitPointsCorridorPart0,int LossPointsCorridorPart0
                     ,double VolumeAlphaStop0,double VolumeAlphaLimit0,double VolumeAlphaMarket0) 
                     : BarBox(OrdersToOneBar0,BarsTotal0)
      {
      VolumeAlphaStop=VolumeAlphaStop0;
      VolumeAlphaLimit=VolumeAlphaLimit0;
      VolumeAlphaMarket=VolumeAlphaMarket0;
      OrdersToOneBar=OrdersToOneBar0;
      HalfCorridorLimitStop=double(HalfCorridorLimitStop0)/double(OrdersToOneBar);
      ExpirationOpenLimit=ExpirationOpenLimit0;
      ExpirationOpenStop=ExpirationOpenStop0;
      ExpirationClose=ExpirationClose0;
      ProfitPointsCorridorPart=ProfitPointsCorridorPart0;
      LossPointsCorridorPart=LossPointsCorridorPart0;
      OrdersToOneBar=OrdersToOneBar0;
      WeightStopLimitFillingType=WeightStopLimitFillingType0;
      }
   private:
   
   double CalcVolumeDecrease(double TypeWeight,int i,int size)// attenuation volume
      {
      if ( size > 1 )
         {
         double K=1.0/(1.0-size);
         double C=1.0;
         return TypeWeight*K*i+C;
         }
      else return 0.0;
      }
      
   double CalcVolumeSimple(double TypeWeight)// equal volume
      {
      return TypeWeight;
      }
   
   void RebuildStops()// rebuild stop orders
      {
      int size=ArraySize(BarOrders[0].BuyStopOrders);
      for ( int j=ArraySize(BarOrders)-1; j>=0; j-- )
         {
         for ( int i=0; i<size; i++ )// reset all
            {
            BarOrders[j].BuyStopOrders[i].Status=STATUS_VIRTUAL;// reset status to initial
            BarOrders[j].BuyStopOrders[i].WantedPrice=Open[j+1]+HalfCorridorLimitStop*(i+1)*Point;// prices of the order grid
            if ( WeightStopLimitFillingType == WEIGHT_DECREASE ) BarOrders[j].BuyStopOrders[i].VolumeAlpha=CalcVolumeDecrease(VolumeAlphaStop,i,size);// weight of each element of the grid
            if ( WeightStopLimitFillingType == WEIGHT_SAME ) BarOrders[j].BuyStopOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaStop);// current weight of each element of the grid
            BarOrders[j].BuyStopOrders[i].VolumeStart=BarOrders[j].BuyStopOrders[i].VolumeAlpha;// starting weight of each element of the grid
            BarOrders[j].BuyStopOrders[i].UpPriceToClose=BarOrders[j].BuyStopOrders[i].WantedPrice+ProfitPointsCorridorPart*Point;// upper border to close
            BarOrders[j].BuyStopOrders[i].LowPriceToClose=BarOrders[j].BuyStopOrders[i].WantedPrice-LossPointsCorridorPart*Point;// lower border to close
            BarOrders[j].BuyStopOrders[i].BarsExpirationOpen=ExpirationOpenStop;
            BarOrders[j].BuyStopOrders[i].BarsExpirationClose=ExpirationClose;
       
            BarOrders[j].SellStopOrders[i].Status=STATUS_VIRTUAL;
            BarOrders[j].SellStopOrders[i].WantedPrice=Open[j+1]-HalfCorridorLimitStop*(i+1)*Point;// prices of the order grid
            if ( WeightStopLimitFillingType == WEIGHT_DECREASE ) BarOrders[j].SellStopOrders[i].VolumeAlpha=CalcVolumeDecrease(VolumeAlphaStop,i,size);// weight of each element of the grid
            if ( WeightStopLimitFillingType == WEIGHT_SAME ) BarOrders[j].SellStopOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaStop);// current weight of each element of the grid
            BarOrders[j].SellStopOrders[i].VolumeStart=BarOrders[j].SellStopOrders[i].VolumeAlpha;// starting weight of each element of the grid
            BarOrders[j].SellStopOrders[i].UpPriceToClose=BarOrders[j].SellStopOrders[i].WantedPrice+LossPointsCorridorPart*Point;// upper border to close
            BarOrders[j].SellStopOrders[i].LowPriceToClose=BarOrders[j].SellStopOrders[i].WantedPrice-ProfitPointsCorridorPart*Point;// lower border to close
            BarOrders[j].SellStopOrders[i].BarsExpirationOpen=ExpirationOpenStop;
            BarOrders[j].SellStopOrders[i].BarsExpirationClose=ExpirationClose;                    
            }         
         }      
      }
      
   void RebuildLimits()// rebuild limit orders
      {
      int size=ArraySize(BarOrders[0].BuyLimitOrders);
      for ( int j=ArraySize(BarOrders)-1; j>=0; j-- )
         {
         for ( int i=0; i<size; i++ )// reset all
            {
            BarOrders[j].BuyLimitOrders[i].Status=STATUS_VIRTUAL;// reset status to initial
            BarOrders[j].BuyLimitOrders[i].WantedPrice=Open[j+1]-HalfCorridorLimitStop*(i+1)*Point;// prices of the order grid
            if ( WeightStopLimitFillingType == WEIGHT_DECREASE ) BarOrders[j].BuyLimitOrders[i].VolumeAlpha=CalcVolumeDecrease(VolumeAlphaLimit,i,size);// weight of each element of the grid
            if ( WeightStopLimitFillingType == WEIGHT_SAME ) BarOrders[j].BuyLimitOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaLimit);// current weight of each element of the grid
            BarOrders[j].BuyLimitOrders[i].VolumeStart=BarOrders[j].BuyLimitOrders[i].VolumeAlpha;// starting weight of each element of the grid
            BarOrders[j].BuyLimitOrders[i].UpPriceToClose=BarOrders[j].BuyLimitOrders[i].WantedPrice+ProfitPointsCorridorPart*Point;// upper border to close
            BarOrders[j].BuyLimitOrders[i].LowPriceToClose=BarOrders[j].BuyLimitOrders[i].WantedPrice-LossPointsCorridorPart*Point;// lower border to close
            BarOrders[j].BuyLimitOrders[i].BarsExpirationOpen=ExpirationOpenLimit;
            BarOrders[j].BuyLimitOrders[i].BarsExpirationClose=ExpirationClose;            
       
            BarOrders[j].SellLimitOrders[i].Status=STATUS_VIRTUAL;
            BarOrders[j].SellLimitOrders[i].WantedPrice=Open[j+1]+HalfCorridorLimitStop*(i+1)*Point;// prices of the order grid
            if ( WeightStopLimitFillingType == WEIGHT_DECREASE ) BarOrders[j].SellLimitOrders[i].VolumeAlpha=CalcVolumeDecrease(VolumeAlphaLimit,i,size);// weight of each element of the grid
            if ( WeightStopLimitFillingType == WEIGHT_SAME ) BarOrders[j].SellLimitOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaLimit);// current weight of each element of the grid
            BarOrders[j].SellLimitOrders[i].VolumeStart=BarOrders[j].SellLimitOrders[i].VolumeAlpha;// starting weight of each element of the grid
            BarOrders[j].SellLimitOrders[i].UpPriceToClose=BarOrders[j].SellLimitOrders[i].WantedPrice+LossPointsCorridorPart*Point;// upper border to close
            BarOrders[j].SellLimitOrders[i].LowPriceToClose=BarOrders[j].SellLimitOrders[i].WantedPrice-ProfitPointsCorridorPart*Point;// lower border to close
            BarOrders[j].SellLimitOrders[i].BarsExpirationOpen=ExpirationOpenLimit;
            BarOrders[j].SellLimitOrders[i].BarsExpirationClose=ExpirationClose;
            }         
         }      
      }
      
   void RebuildMarkets()// rebuild market orders
      {
      int size=ArraySize(BarOrders[0].BuyMarketOrders);
      double MarketStep;
      for ( int j=ArraySize(BarOrders)-1; j>0; j-- )
         {
         MarketStep=(High[j+1]-Low[j+1])/double(OrdersToOneBar);
            
         for ( int i=0; i<size; i++ )// reset all
            {
            BarOrders[j].BuyMarketOrders[i].Status=STATUS_MARKET;// reset status to initial
            BarOrders[j].BuyMarketOrders[i].WantedPrice=Low[j+1]+MarketStep*i;// prices of the order grid
            BarOrders[j].BuyMarketOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaMarket);// current weight of each element of the grid
            BarOrders[j].BuyMarketOrders[i].VolumeStart=BarOrders[j].BuyMarketOrders[i].VolumeAlpha;// starting weight of each element of the grid
            BarOrders[j].BuyMarketOrders[i].UpPriceToClose=BarOrders[j].BuyMarketOrders[i].WantedPrice+ProfitPointsCorridorPart*Point;// upper border to close
            BarOrders[j].BuyMarketOrders[i].LowPriceToClose=BarOrders[j].BuyMarketOrders[i].WantedPrice-LossPointsCorridorPart*Point;// lower border to close
            BarOrders[j].BuyMarketOrders[i].BarsExpirationClose=ExpirationClose;
               
            BarOrders[j].SellMarketOrders[i].Status=STATUS_MARKET;
            BarOrders[j].SellMarketOrders[i].WantedPrice=High[j+1]-MarketStep*i;// prices of the order grid
            BarOrders[j].SellMarketOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaMarket);// current weight of each element of the grid
            BarOrders[j].SellMarketOrders[i].VolumeStart=BarOrders[j].SellMarketOrders[i].VolumeAlpha;// starting weight of each element of the grid
            BarOrders[j].SellMarketOrders[i].UpPriceToClose=BarOrders[j].SellMarketOrders[i].WantedPrice+LossPointsCorridorPart*Point;// upper border to close
            BarOrders[j].SellMarketOrders[i].LowPriceToClose=BarOrders[j].SellMarketOrders[i].WantedPrice-ProfitPointsCorridorPart*Point;// lower border to close
            BarOrders[j].SellMarketOrders[i].BarsExpirationClose=ExpirationClose;
            } 
         }      
      }

   ///// Fast methods
   void RebuildStopsFast()// rebuild stop orders
      {
      int size=ArraySize(BarOrders[0].BuyStopOrders);
      for ( int j=ArraySize(BarOrders)-1; j>0; j-- )
         {
         for ( int i=0; i<size; i++ )// shift orders
            {
            BarOrders[j].BuyStopOrders[i]=BarOrders[j-1].BuyStopOrders[i];
            BarOrders[j].SellStopOrders[i]=BarOrders[j-1].SellStopOrders[i];
            BarOrders[j].SellStopOrders[i].IndexMarket++;
            }
         }
         
      for ( int i=0; i<size; i++ )// create a new grid at a new bar
         {
         BarOrders[0].BuyStopOrders[i].Status=STATUS_VIRTUAL;// reset status to initial
         BarOrders[0].BuyStopOrders[i].WantedPrice=Close[1]+HalfCorridorLimitStop*(i+1)*Point;// prices of the order grid
         if ( WeightStopLimitFillingType == WEIGHT_DECREASE ) BarOrders[0].BuyStopOrders[i].VolumeAlpha=CalcVolumeDecrease(VolumeAlphaStop,i,size);// weight of each element of the grid
         if ( WeightStopLimitFillingType == WEIGHT_SAME ) BarOrders[0].BuyStopOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaStop);// current weight of each element of the grid
         BarOrders[0].BuyStopOrders[i].VolumeStart=BarOrders[0].BuyStopOrders[i].VolumeAlpha;// starting weight of each element of the grid
         BarOrders[0].BuyStopOrders[i].UpPriceToClose=BarOrders[0].BuyStopOrders[i].WantedPrice+ProfitPointsCorridorPart*Point;//upper border to close
         BarOrders[0].BuyStopOrders[i].LowPriceToClose=BarOrders[0].BuyStopOrders[i].WantedPrice-LossPointsCorridorPart*Point;// lower border to close
         BarOrders[0].BuyStopOrders[i].BarsExpirationOpen=ExpirationOpenStop;
         BarOrders[0].BuyStopOrders[i].BarsExpirationClose=ExpirationClose;
       
         BarOrders[0].SellStopOrders[i].Status=STATUS_VIRTUAL;
         BarOrders[0].SellStopOrders[i].WantedPrice=Close[1]-HalfCorridorLimitStop*(i+1)*Point;// prices of the order grid
         if ( WeightStopLimitFillingType == WEIGHT_DECREASE ) BarOrders[0].SellStopOrders[i].VolumeAlpha=CalcVolumeDecrease(VolumeAlphaStop,i,size);// weight of each element of the grid
         if ( WeightStopLimitFillingType == WEIGHT_SAME ) BarOrders[0].SellStopOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaStop);// current weight of each element of the grid
         BarOrders[0].SellStopOrders[i].VolumeStart=BarOrders[0].SellStopOrders[i].VolumeAlpha;// starting weight of each element of the grid
         BarOrders[0].SellStopOrders[i].UpPriceToClose=BarOrders[0].SellStopOrders[i].WantedPrice+LossPointsCorridorPart*Point;// upper border to close
         BarOrders[0].SellStopOrders[i].LowPriceToClose=BarOrders[0].SellStopOrders[i].WantedPrice-ProfitPointsCorridorPart*Point;// lower border to close
         BarOrders[0].SellStopOrders[i].BarsExpirationOpen=ExpirationOpenStop;
         BarOrders[0].SellStopOrders[i].BarsExpirationClose=ExpirationClose;                    
         }               
      }
      
   void RebuildLimitsFast()// rebuild limit orders
      {
      int size=ArraySize(BarOrders[0].BuyLimitOrders);
      for ( int j=ArraySize(BarOrders)-1; j>0; j-- )
         {
         for ( int i=0; i<size; i++ )// shift orders
            {
            BarOrders[j].BuyLimitOrders[i]=BarOrders[j-1].BuyLimitOrders[i];
            BarOrders[j].SellLimitOrders[i]=BarOrders[j-1].SellLimitOrders[i];
            BarOrders[j].SellLimitOrders[i].IndexMarket++;
            }         
         }
      
      for ( int i=0; i<size; i++ )// create a new grid at a new bar
         {
         BarOrders[0].BuyLimitOrders[i].Status=STATUS_VIRTUAL;// reset status to initial
         BarOrders[0].BuyLimitOrders[i].WantedPrice=Open[1]-HalfCorridorLimitStop*(i+1)*Point;// prices of the order grid
         if ( WeightStopLimitFillingType == WEIGHT_DECREASE ) BarOrders[0].BuyLimitOrders[i].VolumeAlpha=CalcVolumeDecrease(VolumeAlphaLimit,i,size);// weight of each element of the grid
         if ( WeightStopLimitFillingType == WEIGHT_SAME ) BarOrders[0].BuyLimitOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaLimit);// current weight of each element of the grid
         BarOrders[0].BuyLimitOrders[i].VolumeStart=BarOrders[0].BuyLimitOrders[i].VolumeAlpha;// starting weight of each element of the grid
         BarOrders[0].BuyLimitOrders[i].UpPriceToClose=BarOrders[0].BuyLimitOrders[i].WantedPrice+ProfitPointsCorridorPart*Point;// upper border to close
         BarOrders[0].BuyLimitOrders[i].LowPriceToClose=BarOrders[0].BuyLimitOrders[i].WantedPrice-LossPointsCorridorPart*Point;// lower border to close
         BarOrders[0].BuyLimitOrders[i].BarsExpirationOpen=ExpirationOpenLimit;
         BarOrders[0].BuyLimitOrders[i].BarsExpirationClose=ExpirationClose;            
       
         BarOrders[0].SellLimitOrders[i].Status=STATUS_VIRTUAL;
         BarOrders[0].SellLimitOrders[i].WantedPrice=Open[1]+HalfCorridorLimitStop*(i+1)*Point;// prices of the order grid
         if ( WeightStopLimitFillingType == WEIGHT_DECREASE ) BarOrders[0].SellLimitOrders[i].VolumeAlpha=CalcVolumeDecrease(VolumeAlphaLimit,i,size);// weight of each element of the grid
         if ( WeightStopLimitFillingType == WEIGHT_SAME ) BarOrders[0].SellLimitOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaLimit);// current weight of each element of the grid
         BarOrders[0].SellLimitOrders[i].VolumeStart=BarOrders[0].SellLimitOrders[i].VolumeAlpha;// starting weight of each element of the grid
         BarOrders[0].SellLimitOrders[i].UpPriceToClose=BarOrders[0].SellLimitOrders[i].WantedPrice+LossPointsCorridorPart*Point;// upper border to close
         BarOrders[0].SellLimitOrders[i].LowPriceToClose=BarOrders[0].SellLimitOrders[i].WantedPrice-ProfitPointsCorridorPart*Point;// lower order to close
         BarOrders[0].SellLimitOrders[i].BarsExpirationOpen=ExpirationOpenLimit;
         BarOrders[0].SellLimitOrders[i].BarsExpirationClose=ExpirationClose;
         }        
      }
      
   void RebuildMarketsFast()// rebuild market orders
      {
      int size=ArraySize(BarOrders[0].BuyMarketOrders);
      double MarketStep;
      for ( int j=ArraySize(BarOrders)-1; j>0; j-- )
         {
         for ( int i=0; i<size; i++ )// shift orders
            {
            BarOrders[j].BuyMarketOrders[i]=BarOrders[j-1].BuyMarketOrders[i];
            BarOrders[j].SellMarketOrders[i]=BarOrders[j-1].SellMarketOrders[i];
            }         
         }
      MarketStep=(High[1]-Low[1])/double(OrdersToOneBar);
      for ( int i=0; i<size; i++ )// create a new grid at a new bar
         {
         BarOrders[0].BuyMarketOrders[i].Status=STATUS_MARKET;// reset status to initial
         BarOrders[0].BuyMarketOrders[i].WantedPrice=Low[1]+MarketStep*i;// prices of the order grid
         BarOrders[0].BuyMarketOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaMarket);// current weight of each element of the grid
         BarOrders[0].BuyMarketOrders[i].VolumeStart=BarOrders[0].BuyMarketOrders[i].VolumeAlpha;// starting weight of each element of the grid
         BarOrders[0].BuyMarketOrders[i].UpPriceToClose=BarOrders[0].BuyMarketOrders[i].WantedPrice+ProfitPointsCorridorPart*Point;// upper border to close
         BarOrders[0].BuyMarketOrders[i].LowPriceToClose=BarOrders[0].BuyMarketOrders[i].WantedPrice-LossPointsCorridorPart*Point;// lower border to close
         BarOrders[0].BuyMarketOrders[i].BarsExpirationClose=ExpirationClose;
               
         BarOrders[0].SellMarketOrders[i].Status=STATUS_MARKET;
         BarOrders[0].SellMarketOrders[i].WantedPrice=High[1]-MarketStep*i;// prices of the order grid
         BarOrders[0].SellMarketOrders[i].VolumeAlpha=CalcVolumeSimple(VolumeAlphaMarket);// current weight of each element of the grid
         BarOrders[0].SellMarketOrders[i].VolumeStart=BarOrders[0].SellMarketOrders[i].VolumeAlpha;// starting weight of each element of the grid
         BarOrders[0].SellMarketOrders[i].UpPriceToClose=BarOrders[0].SellMarketOrders[i].WantedPrice+LossPointsCorridorPart*Point;// upper border to close
         BarOrders[0].SellMarketOrders[i].LowPriceToClose=BarOrders[0].SellMarketOrders[i].WantedPrice-ProfitPointsCorridorPart*Point;// lower border to close
         BarOrders[0].SellMarketOrders[i].BarsExpirationClose=ExpirationClose;
         }         
      }   
   
   protected:
   void CreateNewOrders()// create new orders at each candlestick
      {
      if ( VolumeAlphaStop != 0.0 ) RebuildStops();
      if ( VolumeAlphaLimit != 0.0 ) RebuildLimits();
      if ( VolumeAlphaMarket != 0.0 ) RebuildMarkets();
      }
   
   void CreateNewOrdersFast()//
      {
      if ( VolumeAlphaStop != 0.0 ) RebuildStopsFast();
      if ( VolumeAlphaLimit != 0.0 ) RebuildLimitsFast();
      if ( VolumeAlphaMarket != 0.0 ) RebuildMarketsFast();      
      }
   
   public:   
   virtual void Update()// state updating function (will be expanded in child classes)
      {
      CreateNewOrders();
      }
      
   virtual void UpdateFast()// fast state update
      {
      CreateNewOrdersFast();
      }      
   };

实际上,此类仅创建类似的Update()和UpdateFast()方法的实现,唯一的区别是后者要快得多。这些方法在每个小节上创建新订单,并删除旧订单,从而为下一类准备数据,以模拟订单生命周期。在该类中分配了所有必需的订单参数,包括类型,开盘价,数量和进一步操作所需的其他重要参数。

下一类实现订单模拟过程以及交易所需参数的计算,并根据这些信号生成:

class Simulation:public PositionGenerator // then assemble a simulator of positions (inherited from the position generator)
   {// market parameter calculations will also performed in this class
   protected:
   double BuyPercent;// percent of open Buy positions
   double SellPercent;// percent of open Sell positions
   double StartVolume;// starting total volume of open Buy positions (the same for Buys and Sells)
   double RelativeVolume;// relative volume
   double SummVolumeBuy;// total volume for Buys
   double SummVolumeSell;// total volume for Sells
   
   public:   
   Simulation( ENUM_GRID_WEIGHT WeightStopLimitFillingType0
                     ,int HalfCorridorLimitStop0,int OrdersToOneBar0,int BarsTotal0
                     ,int ExpirationOpenLimit0,int ExpirationOpenStop0
                     ,int ExpirationClose0
                     ,int ProfitPointsCorridorPart0,int LossPointsCorridorPart0
                     ,double VolumeAlphaStop0,double VolumeAlphaLimit0,double VolumeAlphaMarket0) 
   :PositionGenerator(WeightStopLimitFillingType0
                     ,HalfCorridorLimitStop0,OrdersToOneBar0,BarsTotal0
                     ,ExpirationOpenLimit0,ExpirationOpenStop0
                     ,ExpirationClose0
                     ,ProfitPointsCorridorPart0,LossPointsCorridorPart0
                     ,VolumeAlphaStop0,VolumeAlphaLimit0,VolumeAlphaMarket0) 
      {
      CreateNewOrders();
      CalculateStartVolume();// calculate starting volumes
      UpdateVirtual();// first update virtual orders to process part of them as market orders in the next function
      UpdateMarket();// now update the state of all market orders
      CalculateCurrentVolume();// calculate current volumes of all open orders
      CalculatePercent();// calculate the percentage of positions
      CalculateRelativeVolume();// calculate relative volume
      }

   double GetBuyPercent()// get the percentage of open Buy deals
      {
      return BuyPercent;
      }
      
   double GetSellPercent()// get the percentage of open Sell deals
      {
      return SellPercent;
      }
      
   double GetRelativeVolume()// get relative volume
      {
      return RelativeVolume;
      }

   virtual void Update() override
      {
      PositionGenerator::Update();// call everything that was before
      UpdateVirtual();// first update virtual orders to process part of them as market orders in the next function
      UpdateMarket();// now update the state of all market orders
      CalculateCurrentVolume();// calculate current volumes of all open orders
      CalculatePercent();// calculate the percentage of positions
      CalculateRelativeVolume();// calculate relative volume
      }
      
   virtual void UpdateFast() override
      {
      PositionGenerator::UpdateFast();// call everything that was before
      UpdateVirtualFast();// first update virtual orders to process part of them as market orders in the next function
      UpdateMarketFast();// now update the state of all market orders
      CalculateCurrentVolume();// calculate current volumes of all open orders
      CalculatePercent();// calculate the percentage of positions
      CalculateRelativeVolume();// calculate relative volume
      }   
      
   private:
   
   void UpdateVirtual()// update the status of virtual orders
      {
      int size=ArraySize(BarOrders[0].BuyLimitOrders);
      int SizeBarOrders=ArraySize(BarOrders);
      
      if ( VolumeAlphaLimit != 0.0 )
         {
         for ( int i=SizeBarOrders; i>0; i-- )// update the state of limit orders simulating each candlestick
            {
            for ( int j=SizeBarOrders-1; j>i; j-- )// update the state of all candlesticks preceding this one
               {
               for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
                  {
                  if ( BarOrders[j].BuyLimitOrders[k].Status == STATUS_VIRTUAL 
                  && BarOrders[j].BuyLimitOrders[k].WantedPrice <= High[i] 
                  && BarOrders[j].BuyLimitOrders[k].WantedPrice >= Low[i] )// if the order is virtual and is inside a candlestick, then it turns into a market one
                     {
                     BarOrders[j].BuyLimitOrders[k].Status = STATUS_MARKET;
                     BarOrders[j].BuyLimitOrders[k].IndexMarket = i;
                     }
                  if ( BarOrders[j].SellLimitOrders[k].Status == STATUS_VIRTUAL 
                  && BarOrders[j].SellLimitOrders[k].WantedPrice <= High[i] 
                  && BarOrders[j].SellLimitOrders[k].WantedPrice >= Low[i] )// the same
                     {
                     BarOrders[j].SellLimitOrders[k].Status = STATUS_MARKET;
                     BarOrders[j].SellLimitOrders[k].IndexMarket = i;
                     } 
                 
                  /////// Check for interest expiration of limit players
                  if ( BarOrders[j].BuyLimitOrders[k].Status == STATUS_VIRTUAL )//
                     {
                     if ( BarOrders[j].BuyLimitOrders[k].IndexMarket - 1 >= BarOrders[j].BuyLimitOrders[k].BarsExpirationOpen )
                     BarOrders[j].BuyLimitOrders[k].Status=STATUS_ABORTED;
                     else
                        {
                        if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha > 0.0 )
                        BarOrders[j].BuyLimitOrders[k].VolumeAlpha-=BarOrders[j].BuyLimitOrders[k].VolumeStart/double(BarOrders[j].BuyLimitOrders[k].BarsExpirationOpen);
                        if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyLimitOrders[k].VolumeAlpha=0.0;
                        }
                     }
                  if ( BarOrders[j].SellLimitOrders[k].Status == STATUS_VIRTUAL )//
                     {
                     if ( BarOrders[j].SellLimitOrders[k].IndexMarket - 1 >= BarOrders[j].SellLimitOrders[k].BarsExpirationOpen  )
                     BarOrders[j].SellLimitOrders[k].Status=STATUS_ABORTED;
                     else
                        {
                        if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha > 0.0 )
                        BarOrders[j].SellLimitOrders[k].VolumeAlpha-=BarOrders[j].SellLimitOrders[k].VolumeStart/double(BarOrders[j].SellLimitOrders[k].BarsExpirationOpen);
                        if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellLimitOrders[k].VolumeAlpha=0.0;                  
                        }
                     } 
                  }
               }         
            }
         }
         
      if ( VolumeAlphaStop != 0.0 )
         {
         for ( int i=SizeBarOrders; i>0; i-- )// update the state of limit orders simulating each candlestick
            {
            for ( int j=SizeBarOrders-1; j>i; j-- )// update the state of all candlesticks preceding this one
               {
               for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
                  {
                  if ( BarOrders[j].SellStopOrders[k].Status == STATUS_VIRTUAL 
                  && BarOrders[j].SellStopOrders[k].WantedPrice <= High[i] 
                  && BarOrders[j].SellStopOrders[k].WantedPrice >= Low[i] )// the same
                     {
                     BarOrders[j].SellStopOrders[k].Status = STATUS_MARKET;
                     BarOrders[j].SellStopOrders[k].IndexMarket = i;
                     }
                  if ( BarOrders[j].BuyStopOrders[k].Status == STATUS_VIRTUAL 
                  && BarOrders[j].BuyStopOrders[k].WantedPrice <= High[i] 
                  && BarOrders[j].BuyStopOrders[k].WantedPrice >= Low[i] )// the same
                     {
                     BarOrders[j].BuyStopOrders[k].Status = STATUS_MARKET;
                     BarOrders[j].BuyStopOrders[k].IndexMarket = i;
                     }
                  
                  /////// Check for interest expiration of stop and limit players
                  if ( BarOrders[j].BuyStopOrders[k].Status == STATUS_VIRTUAL )//
                     {
                     if ( BarOrders[j].BuyStopOrders[k].IndexMarket - 1 >= BarOrders[j].BuyStopOrders[k].BarsExpirationOpen  )
                     BarOrders[j].BuyStopOrders[k].Status=STATUS_ABORTED;
                     else
                        {
                        if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha > 0.0 )
                        BarOrders[j].BuyStopOrders[k].VolumeAlpha-=BarOrders[j].BuyStopOrders[k].VolumeStart/double(BarOrders[j].BuyStopOrders[k].BarsExpirationOpen);
                        if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyStopOrders[k].VolumeAlpha=0.0;                  
                        } 
                     }
                  if ( BarOrders[j].SellStopOrders[k].Status == STATUS_VIRTUAL )//
                     {
                     if ( BarOrders[j].SellStopOrders[k].IndexMarket - 1 >= BarOrders[j].SellStopOrders[k].BarsExpirationOpen  )
                     BarOrders[j].SellStopOrders[k].Status=STATUS_ABORTED;
                     else
                        {
                        if ( BarOrders[j].SellStopOrders[k].VolumeAlpha > 0.0 )
                        BarOrders[j].SellStopOrders[k].VolumeAlpha-=BarOrders[j].SellStopOrders[k].VolumeStart/double(BarOrders[j].SellStopOrders[k].BarsExpirationOpen);
                        if ( BarOrders[j].SellStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellStopOrders[k].VolumeAlpha=0.0;                     
                        }
                     }                                                                       
                  }
               }         
            }
         }               
      }
      
   void UpdateMarket()// update the status of market orders
      {
      int size=ArraySize(BarOrders[0].BuyLimitOrders);
      int SizeBarOrders=ArraySize(BarOrders);
      
      if ( VolumeAlphaLimit != 0.0 )
         {
         for ( int i=SizeBarOrders; i>1; i-- )// update the state of orders simulating each candlestick
            {
            for ( int j=SizeBarOrders-1; j>i; j-- )// update the state of all candlesticks preceding this one
               {
               for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
                  {
                  // Block for closing when prices change
                  if ( BarOrders[j].BuyLimitOrders[k].Status == STATUS_MARKET )//
                     {
                     if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha > 0.0 )
                        {
                        BarOrders[j].BuyLimitOrders[k].VolumeAlpha-=BarOrders[j].BuyLimitOrders[k].VolumeStart*(High[i]-Open[i])/(BarOrders[j].BuyLimitOrders[k].UpPriceToClose-BarOrders[j].BuyLimitOrders[k].WantedPrice);// with profit
                        BarOrders[j].BuyLimitOrders[k].VolumeAlpha-=BarOrders[j].BuyLimitOrders[k].VolumeStart*(Open[i]-Low[i])/(BarOrders[j].BuyLimitOrders[k].WantedPrice-BarOrders[j].BuyLimitOrders[k].LowPriceToClose);// with loss
                        }
                     if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyLimitOrders[k].VolumeAlpha=0.0;
                     }
                  if ( BarOrders[j].SellLimitOrders[k].Status == STATUS_MARKET )//
                     {
                     if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha > 0.0 )
                        {
                        BarOrders[j].SellLimitOrders[k].VolumeAlpha-=BarOrders[j].SellLimitOrders[k].VolumeStart*(Open[i]-Low[i])/(BarOrders[j].SellLimitOrders[k].WantedPrice-BarOrders[j].SellLimitOrders[k].LowPriceToClose);//with profit
                        BarOrders[j].SellLimitOrders[k].VolumeAlpha-=BarOrders[j].SellLimitOrders[k].VolumeStart*(High[i]-Open[i])/(BarOrders[j].SellLimitOrders[k].UpPriceToClose-BarOrders[j].SellLimitOrders[k].WantedPrice);//with loss
                        }
                     if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellLimitOrders[k].VolumeAlpha=0.0;
                     } 
                  // End of lock for closing when prices change
               
                  // Block for closing when time changes******************************************************
                  if ( BarOrders[j].BuyLimitOrders[k].Status == STATUS_MARKET )//
                     {
                     if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha > 0.0 )
                     BarOrders[j].BuyLimitOrders[k].VolumeAlpha-=BarOrders[j].BuyLimitOrders[k].VolumeStart/double(BarOrders[j].BuyLimitOrders[k].BarsExpirationClose);
                     if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyLimitOrders[k].VolumeAlpha=0.0;
                     }
                  if ( BarOrders[j].SellLimitOrders[k].Status == STATUS_MARKET )//
                     {
                     if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha > 0.0 )
                     BarOrders[j].SellLimitOrders[k].VolumeAlpha-=BarOrders[j].SellLimitOrders[k].VolumeStart/double(BarOrders[j].SellLimitOrders[k].BarsExpirationClose);
                     if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellLimitOrders[k].VolumeAlpha=0.0;
                     } 
                  }
               }         
            }
         }
         
      if ( VolumeAlphaStop != 0.0 )
         {
         for ( int i=SizeBarOrders; i>1; i-- )// update the state of orders simulating each candlestick
            {
            for ( int j=SizeBarOrders-1; j>i; j-- )// update the state of all candlesticks preceding this one
               {
               for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
                  {
                  // Block for closing when prices change
                  if ( BarOrders[j].BuyStopOrders[k].Status == STATUS_MARKET )//
                     {
                     if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha > 0.0 )
                        {
                        BarOrders[j].BuyStopOrders[k].VolumeAlpha-=BarOrders[j].BuyStopOrders[k].VolumeStart*(High[i]-Open[i])/(BarOrders[j].BuyStopOrders[k].UpPriceToClose-BarOrders[j].BuyStopOrders[k].WantedPrice);// with profit
                        BarOrders[j].BuyStopOrders[k].VolumeAlpha-=BarOrders[j].BuyStopOrders[k].VolumeStart*(Open[i]-Low[i])/(BarOrders[j].BuyStopOrders[k].WantedPrice-BarOrders[j].BuyStopOrders[k].LowPriceToClose);// with loss
                        }
                     if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyStopOrders[k].VolumeAlpha=0.0;
                     }
                  if ( BarOrders[j].SellStopOrders[k].Status == STATUS_MARKET )//
                     {
                     if ( BarOrders[j].SellStopOrders[k].VolumeAlpha > 0.0 )
                        {
                        BarOrders[j].SellStopOrders[k].VolumeAlpha-=BarOrders[j].SellStopOrders[k].VolumeStart*(Open[i]-Low[i])/(BarOrders[j].SellStopOrders[k].WantedPrice-BarOrders[j].SellStopOrders[k].LowPriceToClose);//with profit
                        BarOrders[j].SellStopOrders[k].VolumeAlpha-=BarOrders[j].SellStopOrders[k].VolumeStart*(High[i]-Open[i])/(BarOrders[j].SellStopOrders[k].UpPriceToClose-BarOrders[j].SellStopOrders[k].WantedPrice);//with loss
                        }
                     if ( BarOrders[j].SellStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellStopOrders[k].VolumeAlpha=0.0;
                     }
               
                  // End of lock for closing when prices change
               
                  // Block for closing when time changes******************************************************
                  if ( BarOrders[j].BuyStopOrders[k].Status == STATUS_MARKET )//
                     {
                     if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha > 0.0 )
                     BarOrders[j].BuyStopOrders[k].VolumeAlpha-=BarOrders[j].BuyStopOrders[k].VolumeStart/double(BarOrders[j].BuyStopOrders[k].BarsExpirationClose);
                     if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyStopOrders[k].VolumeAlpha=0.0;
                     }
                  if ( BarOrders[j].SellStopOrders[k].Status == STATUS_MARKET )//
                     {
                     if ( BarOrders[j].SellStopOrders[k].VolumeAlpha > 0.0 )
                     BarOrders[j].SellStopOrders[k].VolumeAlpha-=BarOrders[j].SellStopOrders[k].VolumeStart/double(BarOrders[j].SellStopOrders[k].BarsExpirationClose);
                     if ( BarOrders[j].SellStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellStopOrders[k].VolumeAlpha=0.0;
                     }
                  }
               }         
            }
         }
         
      if ( VolumeAlphaMarket != 0.0 )
         {
         for ( int i=SizeBarOrders; i>1; i-- )// update the state of orders simulating each candlestick
            {
            for ( int j=SizeBarOrders-1; j>i; j-- )// update the state of all candlesticks preceding this one
               {
               for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
                  {
                  // Block for closing when prices change
                  /// For obviously market positions
                  if ( BarOrders[j].BuyMarketOrders[k].VolumeAlpha > 0.0 )
                     {
                     BarOrders[j].BuyMarketOrders[k].VolumeAlpha-=BarOrders[j].BuyMarketOrders[k].VolumeStart*(High[i]-Open[i])/(BarOrders[j].BuyMarketOrders[k].UpPriceToClose-BarOrders[j].BuyMarketOrders[k].WantedPrice);// with profit
                     BarOrders[j].BuyMarketOrders[k].VolumeAlpha-=BarOrders[j].BuyMarketOrders[k].VolumeStart*(Open[i]-Low[i])/(BarOrders[j].BuyMarketOrders[k].WantedPrice-BarOrders[j].BuyMarketOrders[k].LowPriceToClose);// with loss
                     }
                  if ( BarOrders[j].BuyMarketOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyMarketOrders[k].VolumeAlpha=0.0;
                              
                  if ( BarOrders[j].SellMarketOrders[k].VolumeAlpha > 0.0 )
                     {
                     BarOrders[j].SellMarketOrders[k].VolumeAlpha-=BarOrders[j].SellMarketOrders[k].VolumeStart*(Open[i]-Low[i])/(BarOrders[j].SellMarketOrders[k].WantedPrice-BarOrders[j].SellMarketOrders[k].LowPriceToClose);// with profit
                     BarOrders[j].SellMarketOrders[k].VolumeAlpha-=BarOrders[j].SellMarketOrders[k].VolumeStart*(High[i]-Open[i])/(BarOrders[j].SellMarketOrders[k].UpPriceToClose-BarOrders[j].SellMarketOrders[k].WantedPrice);// with loss
                     }
                  if ( BarOrders[j].SellMarketOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellMarketOrders[k].VolumeAlpha=0.0;                  
                  // End of lock for closing when prices change
               
                  // Block for closing when time changes******************************************************
              
                  /// For obviously market positions
                  if ( BarOrders[j].BuyMarketOrders[k].VolumeAlpha > 0.0 )
                  BarOrders[j].BuyMarketOrders[k].VolumeAlpha-=BarOrders[j].BuyMarketOrders[k].VolumeStart/double(BarOrders[j].BuyMarketOrders[k].BarsExpirationClose);
                  if ( BarOrders[j].BuyMarketOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyMarketOrders[k].VolumeAlpha=0.0;
                  if ( BarOrders[j].SellMarketOrders[k].VolumeAlpha > 0.0 )
                  BarOrders[j].SellMarketOrders[k].VolumeAlpha-=BarOrders[j].SellMarketOrders[k].VolumeStart/double(BarOrders[j].SellMarketOrders[k].BarsExpirationClose);
                  if ( BarOrders[j].SellMarketOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellMarketOrders[k].VolumeAlpha=0.0;               
                  //
                  }
               }         
            }
         }
      }
      
   /// fast methods****   
   void UpdateVirtualFast()// update the status of virtual orders
      {
      int SizeBarOrders=ArraySize(BarOrders);
      int size=ArraySize(BarOrders[0].BuyLimitOrders);
      
      if ( VolumeAlphaLimit != 0.0 )
         {
         for ( int j=SizeBarOrders-1; j>0; j-- )// update the state of all candlesticks preceding this one
            {
            for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
               {
               if ( BarOrders[j].BuyLimitOrders[k].Status == STATUS_VIRTUAL 
               && BarOrders[j].BuyLimitOrders[k].WantedPrice <= High[1] 
               && BarOrders[j].BuyLimitOrders[k].WantedPrice >= Low[1] )// if the order is virtual and is inside a candlestick, then it turns into a market one
                  {
                  BarOrders[j].BuyLimitOrders[k].Status = STATUS_MARKET;
                  BarOrders[j].BuyLimitOrders[k].IndexMarket = 1;
                  }
               if ( BarOrders[j].SellLimitOrders[k].Status == STATUS_VIRTUAL 
               && BarOrders[j].SellLimitOrders[k].WantedPrice <= High[1] 
               && BarOrders[j].SellLimitOrders[k].WantedPrice >= Low[1] )// the same
                  {
                  BarOrders[j].SellLimitOrders[k].Status = STATUS_MARKET;
                  BarOrders[j].SellLimitOrders[k].IndexMarket = 1;
                  } 
                  
               /////// Check for interest expiration of limit players
               if ( BarOrders[j].BuyLimitOrders[k].Status == STATUS_VIRTUAL )//
                  {
                  if ( BarOrders[j].BuyLimitOrders[k].IndexMarket - 1 >= BarOrders[j].BuyLimitOrders[k].BarsExpirationOpen )
                  BarOrders[j].BuyLimitOrders[k].Status=STATUS_ABORTED;
                  else
                     {
                     if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha > 0.0 )
                     BarOrders[j].BuyLimitOrders[k].VolumeAlpha-=BarOrders[j].BuyLimitOrders[k].VolumeStart/double(BarOrders[j].BuyLimitOrders[k].BarsExpirationOpen);
                     if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyLimitOrders[k].VolumeAlpha=0.0;
                     }
                  }
               if ( BarOrders[j].SellLimitOrders[k].Status == STATUS_VIRTUAL )//
                  {
                  if ( BarOrders[j].SellLimitOrders[k].IndexMarket - 1 >= BarOrders[j].SellLimitOrders[k].BarsExpirationOpen  )
                  BarOrders[j].SellLimitOrders[k].Status=STATUS_ABORTED;
                  else
                     {
                     if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha > 0.0 )
                     BarOrders[j].SellLimitOrders[k].VolumeAlpha-=BarOrders[j].SellLimitOrders[k].VolumeStart/double(BarOrders[j].SellLimitOrders[k].BarsExpirationOpen);
                     if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellLimitOrders[k].VolumeAlpha=0.0;                  
                     }
                  } 
               }
            }
         }
         
      if ( VolumeAlphaStop != 0.0 )
         {       
         for ( int j=SizeBarOrders-1; j>0; j-- )// update the state of all candlesticks preceding this one
            {
            for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
               {
               if ( BarOrders[j].SellStopOrders[k].Status == STATUS_VIRTUAL 
               && BarOrders[j].SellStopOrders[k].WantedPrice <= High[1] 
               && BarOrders[j].SellStopOrders[k].WantedPrice >= Low[1] )// the same
                  {
                  BarOrders[j].SellStopOrders[k].Status = STATUS_MARKET;
                  BarOrders[j].SellStopOrders[k].IndexMarket = 1;
                  }
               if ( BarOrders[j].BuyStopOrders[k].Status == STATUS_VIRTUAL 
               && BarOrders[j].BuyStopOrders[k].WantedPrice <= High[1] 
               && BarOrders[j].BuyStopOrders[k].WantedPrice >= Low[1] )// the same
                  {
                  BarOrders[j].BuyStopOrders[k].Status = STATUS_MARKET;
                  BarOrders[j].BuyStopOrders[k].IndexMarket = 1;
                  }
                  
               /////// Check for interest expiration of stop players
               if ( BarOrders[j].BuyStopOrders[k].Status == STATUS_VIRTUAL )//
                  {
                  if ( BarOrders[j].BuyStopOrders[k].IndexMarket - 1 >= BarOrders[j].BuyStopOrders[k].BarsExpirationOpen  )
                  BarOrders[j].BuyStopOrders[k].Status=STATUS_ABORTED;
                  else
                     {
                     if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha > 0.0 )
                     BarOrders[j].BuyStopOrders[k].VolumeAlpha-=BarOrders[j].BuyStopOrders[k].VolumeStart/double(BarOrders[j].BuyStopOrders[k].BarsExpirationOpen);
                     if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyStopOrders[k].VolumeAlpha=0.0;                  
                     } 
                  }
               if ( BarOrders[j].SellStopOrders[k].Status == STATUS_VIRTUAL )//
                  {
                  if ( BarOrders[j].SellStopOrders[k].IndexMarket - 1 >= BarOrders[j].SellStopOrders[k].BarsExpirationOpen  )
                  BarOrders[j].SellStopOrders[k].Status=STATUS_ABORTED;
                  else
                     {
                     if ( BarOrders[j].SellStopOrders[k].VolumeAlpha > 0.0 )
                     BarOrders[j].SellStopOrders[k].VolumeAlpha-=BarOrders[j].SellStopOrders[k].VolumeStart/double(BarOrders[j].SellStopOrders[k].BarsExpirationOpen);
                     if ( BarOrders[j].SellStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellStopOrders[k].VolumeAlpha=0.0;                     
                     }
                  }                                                                       
               }
            }
         }         
      }
      
   void UpdateMarketFast()// update the status of market orders
      {
      int size=ArraySize(BarOrders[0].BuyLimitOrders);
      int SizeBarOrders=ArraySize(BarOrders);
      
      if ( VolumeAlphaLimit != 0.0 )
         {
         for ( int j=SizeBarOrders-1; j>0; j-- )// update the state of all candlesticks preceding this one
            {
            for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
               {
               // Block for closing when prices change
               if ( BarOrders[j].BuyLimitOrders[k].Status == STATUS_MARKET )//
                  {
                  if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha > 0.0 )
                     {
                     BarOrders[j].BuyLimitOrders[k].VolumeAlpha-=BarOrders[j].BuyLimitOrders[k].VolumeStart*(High[1]-Open[1])/(BarOrders[j].BuyLimitOrders[k].UpPriceToClose-BarOrders[j].BuyLimitOrders[k].WantedPrice);// with profit
                     BarOrders[j].BuyLimitOrders[k].VolumeAlpha-=BarOrders[j].BuyLimitOrders[k].VolumeStart*(Open[1]-Low[1])/(BarOrders[j].BuyLimitOrders[k].WantedPrice-BarOrders[j].BuyLimitOrders[k].LowPriceToClose);// with loss
                     }
                  if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyLimitOrders[k].VolumeAlpha=0.0;
                  }
               if ( BarOrders[j].SellLimitOrders[k].Status == STATUS_MARKET )//
                  {
                  if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha > 0.0 )
                     {
                     BarOrders[j].SellLimitOrders[k].VolumeAlpha-=BarOrders[j].SellLimitOrders[k].VolumeStart*(Open[1]-Low[1])/(BarOrders[j].SellLimitOrders[k].WantedPrice-BarOrders[j].SellLimitOrders[k].LowPriceToClose);// with profit
                     BarOrders[j].SellLimitOrders[k].VolumeAlpha-=BarOrders[j].SellLimitOrders[k].VolumeStart*(High[1]-Open[1])/(BarOrders[j].SellLimitOrders[k].UpPriceToClose-BarOrders[j].SellLimitOrders[k].WantedPrice);// with loss
                     }
                  if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellLimitOrders[k].VolumeAlpha=0.0;
                  } 
               // End of lock for closing when prices change
               
               // Block for closing when time changes******************************************************
               if ( BarOrders[j].BuyLimitOrders[k].Status == STATUS_MARKET )//
                  {
                  if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha > 0.0 )
                  BarOrders[j].BuyLimitOrders[k].VolumeAlpha-=BarOrders[j].BuyLimitOrders[k].VolumeStart/double(BarOrders[j].BuyLimitOrders[k].BarsExpirationClose);
                  if ( BarOrders[j].BuyLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyLimitOrders[k].VolumeAlpha=0.0;
                  }
               if ( BarOrders[j].SellLimitOrders[k].Status == STATUS_MARKET )//
                  {
                  if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha > 0.0 )
                  BarOrders[j].SellLimitOrders[k].VolumeAlpha-=BarOrders[j].SellLimitOrders[k].VolumeStart/double(BarOrders[j].SellLimitOrders[k].BarsExpirationClose);
                  if ( BarOrders[j].SellLimitOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellLimitOrders[k].VolumeAlpha=0.0;
                  } 
               //
               }
            }
         }
         
      if ( VolumeAlphaStop != 0.0 )
         {
         for ( int j=SizeBarOrders-1; j>0; j-- )// update the state of all candlesticks preceding this one
            {
            for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
               {
               // Block for closing when prices change
               if ( BarOrders[j].BuyStopOrders[k].Status == STATUS_MARKET )//
                  {
                  if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha > 0.0 )
                     {
                     BarOrders[j].BuyStopOrders[k].VolumeAlpha-=BarOrders[j].BuyStopOrders[k].VolumeStart*(High[1]-Open[1])/(BarOrders[j].BuyStopOrders[k].UpPriceToClose-BarOrders[j].BuyStopOrders[k].WantedPrice);// with profit
                     BarOrders[j].BuyStopOrders[k].VolumeAlpha-=BarOrders[j].BuyStopOrders[k].VolumeStart*(Open[1]-Low[1])/(BarOrders[j].BuyStopOrders[k].WantedPrice-BarOrders[j].BuyStopOrders[k].LowPriceToClose);// with loss
                     }
                  if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyStopOrders[k].VolumeAlpha=0.0;
                  }
               if ( BarOrders[j].SellStopOrders[k].Status == STATUS_MARKET )//
                  {
                  if ( BarOrders[j].SellStopOrders[k].VolumeAlpha > 0.0 )
                     {
                     BarOrders[j].SellStopOrders[k].VolumeAlpha-=BarOrders[j].SellStopOrders[k].VolumeStart*(Open[1]-Low[1])/(BarOrders[j].SellStopOrders[k].WantedPrice-BarOrders[j].SellStopOrders[k].LowPriceToClose);// with profit
                     BarOrders[j].SellStopOrders[k].VolumeAlpha-=BarOrders[j].SellStopOrders[k].VolumeStart*(High[1]-Open[1])/(BarOrders[j].SellStopOrders[k].UpPriceToClose-BarOrders[j].SellStopOrders[k].WantedPrice);// with loss
                     }
                  if ( BarOrders[j].SellStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellStopOrders[k].VolumeAlpha=0.0;
                  }
               
               // End of lock for closing when prices change
               
               // Block for closing when time changes******************************************************
               if ( BarOrders[j].BuyStopOrders[k].Status == STATUS_MARKET )//
                  {
                  if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha > 0.0 )
                  BarOrders[j].BuyStopOrders[k].VolumeAlpha-=BarOrders[j].BuyStopOrders[k].VolumeStart/double(BarOrders[j].BuyStopOrders[k].BarsExpirationClose);
                  if ( BarOrders[j].BuyStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyStopOrders[k].VolumeAlpha=0.0;
                  }
               if ( BarOrders[j].SellStopOrders[k].Status == STATUS_MARKET )//
                  {
                  if ( BarOrders[j].SellStopOrders[k].VolumeAlpha > 0.0 )
                  BarOrders[j].SellStopOrders[k].VolumeAlpha-=BarOrders[j].SellStopOrders[k].VolumeStart/double(BarOrders[j].SellStopOrders[k].BarsExpirationClose);
                  if ( BarOrders[j].SellStopOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellStopOrders[k].VolumeAlpha=0.0;
                  }
               //
               }
            }
         }
         
       if ( VolumeAlphaMarket != 0.0 )
         {
         for ( int j=SizeBarOrders-1; j>0; j-- )// update the state of all candlesticks preceding this one
            {
            for ( int k=0; k<size; k++ )// update the state inside each preceding candlestick
               {
               /// For obviously market positions
               if ( BarOrders[j].BuyMarketOrders[k].VolumeAlpha > 0.0 )
                  {
                  BarOrders[j].BuyMarketOrders[k].VolumeAlpha-=BarOrders[j].BuyMarketOrders[k].VolumeStart*(High[1]-Open[1])/(BarOrders[j].BuyMarketOrders[k].UpPriceToClose-BarOrders[j].BuyMarketOrders[k].WantedPrice);// with profit
                  BarOrders[j].BuyMarketOrders[k].VolumeAlpha-=BarOrders[j].BuyMarketOrders[k].VolumeStart*(Open[1]-Low[1])/(BarOrders[j].BuyMarketOrders[k].WantedPrice-BarOrders[j].BuyMarketOrders[k].LowPriceToClose);// with loss
                  }
               if ( BarOrders[j].BuyMarketOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyMarketOrders[k].VolumeAlpha=0.0;
                              
               if ( BarOrders[j].SellMarketOrders[k].VolumeAlpha > 0.0 )
                  {
                  BarOrders[j].SellMarketOrders[k].VolumeAlpha-=BarOrders[j].SellMarketOrders[k].VolumeStart*(Open[1]-Low[1])/(BarOrders[j].SellMarketOrders[k].WantedPrice-BarOrders[j].SellMarketOrders[k].LowPriceToClose);// with profit
                  BarOrders[j].SellMarketOrders[k].VolumeAlpha-=BarOrders[j].SellMarketOrders[k].VolumeStart*(High[1]-Open[1])/(BarOrders[j].SellMarketOrders[k].UpPriceToClose-BarOrders[j].SellMarketOrders[k].WantedPrice);// with loss
                  }
               if ( BarOrders[j].SellMarketOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellMarketOrders[k].VolumeAlpha=0.0;                  
               // End of lock for closing when prices change
               
               // Block for closing when time changes******************************************************
             
               /// For obviously market positions
               if ( BarOrders[j].BuyMarketOrders[k].VolumeAlpha > 0.0 )
               BarOrders[j].BuyMarketOrders[k].VolumeAlpha-=BarOrders[j].BuyMarketOrders[k].VolumeStart/double(BarOrders[j].BuyMarketOrders[k].BarsExpirationClose);
               if ( BarOrders[j].BuyMarketOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].BuyMarketOrders[k].VolumeAlpha=0.0;
               if ( BarOrders[j].SellMarketOrders[k].VolumeAlpha > 0.0 )
               BarOrders[j].SellMarketOrders[k].VolumeAlpha-=BarOrders[j].SellMarketOrders[k].VolumeStart/double(BarOrders[j].SellMarketOrders[k].BarsExpirationClose);
               if ( BarOrders[j].SellMarketOrders[k].VolumeAlpha < 0.0 ) BarOrders[j].SellMarketOrders[k].VolumeAlpha=0.0;               
               //
               }
            }
         }                          
      }      
   ///******
      
   void CalculateStartVolume()// calculate the starting total volume of all positions (relative to it we will estimate market fullness)
      {
      StartVolume=0;
      int size=ArraySize(BarOrders[0].BuyStopOrders);
      if ( VolumeAlphaStop != 0.0 )
         {
         for ( int j=ArraySize(BarOrders)-1; j>=0; j-- )
            {
            for ( int i=0; i<size; i++ )
               {
               StartVolume+=BarOrders[j].BuyStopOrders[i].VolumeStart;
               }
            }        
         }
         
      if ( VolumeAlphaLimit != 0.0 )
         {
         size=ArraySize(BarOrders[0].BuyLimitOrders);
         for ( int j=ArraySize(BarOrders)-1; j>=0; j-- )
            {
            for ( int i=0; i<size; i++ )
               {
               StartVolume+=BarOrders[j].BuyLimitOrders[i].VolumeStart;
               }         
            }
         }
         
      if ( VolumeAlphaMarket != 0.0 )
         {
         size=ArraySize(BarOrders[0].BuyMarketOrders);
         for ( int j=ArraySize(BarOrders)-1; j>=0; j-- )
            {
            for ( int i=0; i<size; i++ )
               {
               StartVolume+=BarOrders[j].BuyMarketOrders[i].VolumeStart;
               }         
            }
         }         
      }
      
   void CalculateCurrentVolume()// calculate the current total volume of all positions
      {
      SummVolumeBuy=0;
      SummVolumeSell=0;
      int size=ArraySize(BarOrders[0].BuyStopOrders);
      
      if ( VolumeAlphaStop != 0.0 )
         {
         for ( int j=ArraySize(BarOrders)-1; j>=0; j-- )
            {
            for ( int i=0; i<size; i++ )
               {
               if ( BarOrders[j].BuyStopOrders[i].Status == STATUS_MARKET )
               SummVolumeBuy+=BarOrders[j].BuyStopOrders[i].VolumeAlpha;
               if ( BarOrders[j].SellStopOrders[i].Status == STATUS_MARKET )
               SummVolumeSell+=BarOrders[j].SellStopOrders[i].VolumeAlpha;            
               }         
            }
         }
      
      if ( VolumeAlphaLimit != 0.0 )
         {   
         size=ArraySize(BarOrders[0].BuyLimitOrders);
         for ( int j=ArraySize(BarOrders)-1; j>=0; j-- )
            {
            for ( int i=0; i<size; i++ )
               {
               if ( BarOrders[j].BuyLimitOrders[i].Status == STATUS_MARKET )
               SummVolumeBuy+=BarOrders[j].BuyLimitOrders[i].VolumeAlpha;
               if ( BarOrders[j].SellLimitOrders[i].Status == STATUS_MARKET )
               SummVolumeSell+=BarOrders[j].SellLimitOrders[i].VolumeAlpha;            
               }         
            }
         }
      
      if ( VolumeAlphaMarket != 0.0 )
         {
         size=ArraySize(BarOrders[0].BuyMarketOrders);
         for ( int j=ArraySize(BarOrders)-1; j>=0; j-- )
            {
            for ( int i=0; i<size; i++ )
               {
               SummVolumeBuy+=BarOrders[j].BuyMarketOrders[i].VolumeAlpha;
               SummVolumeSell+=BarOrders[j].SellMarketOrders[i].VolumeAlpha;
               }         
            }
         }         
      }
      
   void CalculatePercent()// calculate the percentage of Buys and Sells relative to all positions
      {
      if ( (SummVolumeBuy+SummVolumeSell) != 0.0 ) BuyPercent=100.0*SummVolumeBuy/(SummVolumeBuy+SummVolumeSell);
      else BuyPercent=50;
      if ( (SummVolumeBuy+SummVolumeSell) != 0.0 ) SellPercent=100.0*SummVolumeSell/(SummVolumeBuy+SummVolumeSell);
      else SellPercent=50;
      }      
      
   void CalculateRelativeVolume()// calculate relative volumes of Buys and Sells (calculate only uncovered part of positions)
      {
      if ( SummVolumeBuy >= SummVolumeSell ) RelativeVolume=(SummVolumeBuy-SummVolumeSell)/StartVolume;
      else RelativeVolume=(SummVolumeSell-SummVolumeBuy)/StartVolume;
      }                   
   
   };

整个代码对MetaTrader 4和MetaTrader 5均有效。可以在两个平台上编译这些类。当然,在MetaTrader 5中,您应该预先实现预定义的数组,与MQL4中相同。我将不在此处提供此代码。您可以在随附的源代码中对其进行检查。我的代码不是很原始。我们现在要做的就是实现负责交易的变量以及相关功能。两个终端的EA交易如下。

该代码占用大量资源,这就是为什么我组织缓慢的逻辑实现来开始分析,而组织快速的实现来处理条形图。我所有的EA交易均采用条形图,以避免依赖于人工价格变动的产生以及每次价格变动测试的其他不良后果。当然,我们可以完全避免功能缓慢。但是在这种情况下,将没有开始的分析。而且,我不喜欢在类主体之外实现功能,因为我认为这会破坏图片的完整性。

最后一个类的构造函数将接受以下参数,这些参数将作为输入。如果您愿意,可以进行许多这样的模拟,因为它只是一个类实例:

input bool bPrintE=false;// print market parameters
input CLOSE_MODE CloseModeE=CLOSE_FAST;// order closing mode
input WORK_MODE ModeE=MODE_SIMPLE;// simulation mode
input ENUM_GRID_WEIGHT WeightFillingE=WEIGHT_SAME;// weight distribution type
input double LimitVolumeE=0.5;// significance of limit orders
input double StopVolumeE=0.5;// significance of stop orders
input double MarketVolume=0.5;// significance of market orders
input int ExpirationBars=100;// bars for full expiration of open orders
input int ExpirationOpenStopBars=1000;// patience of a stop player in bars, after which the order is canceled
input int ExpirationOpenLimitBars=1000;// patience of a limit player in bars, after which the order is canceled
input int ProfitPointsCloseE=200;// points to close with profit
input int LossPointsCloseE=400;// points to close with loss
input int HalfCorridorE=500;// half-corridor for limit and stop orders
input int OrdersToOneBarE=50;// orders for half-grid per 1 bar
input int BarsE=250;// bars for analysis
input double MinPercentE=60;// minimum superiority of one trading side in percentage 
input double MaxPercentE=80;// maximum percentage
input double MinRelativeVolumeE=0.0001;// minimum market filling [0...1]
input double MaxRelativeVolumeE=1.00;// maximum market filling [0...1]

我不会在这里提供与交易相关的变量,因为一切都很简单明了。 

这是我执行交易的功能:

void Trade()
   {
   if ( Area0 == NULL )
      {
      CalcAllMQL5Values();
      Area0 = new Simulation(WeightFillingE,HalfCorridorE,OrdersToOneBarE,BarsE
       ,ExpirationOpenLimitBars,ExpirationOpenStopBars,ExpirationBars,ProfitPointsCloseE,LossPointsCloseE
       ,StopVolumeE,LimitVolumeE,MarketVolume);      
      }
   
   switch(ModeE)
      {
      case MODE_SIMPLE:
         Area0.Update();// update simulation
      case MODE_FAST:
         Area0.UpdateFast();// fast update simulation
      }
   
   if (bPrintE)
      {
      Print("BuyPercent= ",Area0.GetBuyPercent());
      Print("SellPercent= ",Area0.GetSellPercent());
      Print("RelativeVolume= ",Area0.GetRelativeVolume());
      }
      
   if ( CloseModeE == CLOSE_FAST && Area0.GetBuyPercent() > 50.0 )
      {
      if ( !bInvert ) CloseBuyF();
      else CloseSellF();
      }
      
   if ( CloseModeE == CLOSE_FAST && Area0.GetSellPercent() > 50.0 )
      {
      if ( !bInvert ) CloseSellF();
      else CloseBuyF();
      }      
      
   if ( Area0.GetBuyPercent() > MinPercentE && Area0.GetBuyPercent() < MaxPercentE 
   && Area0.GetRelativeVolume() >= MinRelativeVolumeE && Area0.GetRelativeVolume() <= MaxRelativeVolumeE )
      {
      if ( !bInvert )
         {
         CloseBuyF();
         SellF();
         }
      else
         {
         CloseSellF();
         BuyF();
         }   
      }
      
   if ( Area0.GetSellPercent() > MinPercentE && Area0.GetSellPercent() < MaxPercentE 
   && Area0.GetRelativeVolume() >= MinRelativeVolumeE && Area0.GetRelativeVolume() <= MaxRelativeVolumeE )
      {
      if ( !bInvert )    
         {
         CloseSellF();
         BuyF();
         }  
      else
         {
         CloseBuyF();
         SellF();
         }
      }
   }

如果需要的话,可以提供更好的交易条件和更复杂的功能,但是到目前为止,我还没有意识到这一点。我总是尝试将交易与逻辑部分分开。逻辑在对象中实现。第一次触发时,将在交易功能中动态创建模拟对象;在初始化期间将其删除。这是因为MQL5中的预定义数组不可用,必须人工创建它们以确保类似于MQL4的类操作。


如何找到工作设置?

根据我的经验,可以说最好手动选择设置。此外,对于在较低时间范围内运行且数学期望较小的EA交易,我建议忽略第一阶段的价差-这将帮助您从一开始就不会错过性能指标。 MetaTrader 4非常适合此目的。成功搜索之后,总是要进行修订,编辑等操作,以提高最终的数学期望和利润因子(信号强度)。同样,理想情况下,输入数据的结构应允许独立的操作模式。换句话说,一个设置应该对系统性能具有最独立的影响,而不管其他设置的值如何。通过设置将所有找到的信号组合在一起的平衡设置,此方法可以增强整体信号。这样的实现并非总是可能的,但是在我们的情况下,由于我们分别分析每种订单类型,因此它是适用的。


测试EA交易

从头开始编写本EA交易,没有任何准备。因此,此EA代码对我来说是新的。我有一个类似的EA,但它简单得多,逻辑也完全不同。我想强调这一点,因为本文的目的是表明任何具有一些正确基础知识的想法,即使它不能完全描述市场物理学,也很有可能表现出一些性能。如果该系统显示出基本的性能,我们可以对其进行测试,找到在该系统中有效的方法,并进一步提高对市场的了解。下一阶段假设您将自己创建更高质量的EA交易。

在测试EA交易时,我不得不花几天耐心地选择交易参数。一切都很无聊且漫长,但我设法找到了工作设置。当然,这些设置非常弱,并且仅使用一种订单类型执行仿真,但这是有意进行的。因为最好是分别分析特定订单类型如何影响信号,然后尝试模拟其他订单类型,所以更好。这是我在MetaTrader 4中的结果:

欧元/美元2010.01.01 -2020.11.01

我首先为MetaTrader 4创建了一个版本,并以尽可能低的价差进行了测试。事实是,我们需要查看每个刻度以搜索模式,尤其是在较短的时间范围内。在测试MetaTrader 5版本时,由于价差,我们看不到,MetaTester 5可以自行调整。

这是用于压力测试和评估实际系统性能的理想工具。应该在最后阶段使用它来实时测试系统。在我们的情况下,最好在MetaTrader 4中开始测试系统。我建议所有人都使用这种方法,因为如果您立即开始在第五版中进行测试,则可能会丢失很多出色的设置选项,这些设置选项可以用作高质量设置的基础。

由于许多原因,我不建议使用优化,但是主要原因是它是参数的简单迭代。如果不手动尝试参数,则将无法理解其工作原理。如果您使用旧收音机,请将电动机连接到其手柄上并启动它们,很可能您将找不到广播电台。同样的事情在这里发生。即使您设法抓住某些东西,也很难理解它是什么。

另一个非常重要的方面是订单数量。相对于柱线数量打开的订单越多,发现的物理性就越强,并且将来您不必理会它的性能。还要记住,发现的模式可能位于价差内,如果这些时刻不受控制,会使系统无用!

这是我们需要MetaTrader 5测试器的地方。 MetaTrader 5允许使用真实报价来测试策略。不幸的是,所有货币对和工具在最近一段时间都存在真实的价格变动。我将使用真实报价和非常严格的点差要求在最后一次测试MetaTrader 5的系统版本,以查看该系统是否在2020年能正常工作。但是,首先,我将在之前使用的时间段内以“每个报价”模式测试该系统:

此测试模式不如使用真实刻度的测试模式好。但是,很明显,最初结果中只有很小一部分信号保留在这里。然而,仍然有一些信号可以覆盖点差,甚至带来微利。另外,我不确定测试人员从深厚的历史中获得的利差。在此测试中,手数为0.01,这意味着数学期望值为5点,甚至比原始测试的期望值还要高,尽管该图表看起来不是很好。仍然可以信任此数据,因为在其背后的初始测试中有100,000个交易的大量样本。

现在让我们看一下去年:

在此测试中,我将手数设置为0.1,因此考虑到MetaTrader 4的初始测试只有3点的期望,数学上的期望值为23.4点,这是非常好的。未来的期望可能会下降,但不会降低很多。因此,对于盈亏平衡交易来说仍然足够。

下面的附件中提供了两个终端的EA交易。您可以更改设置并尝试查找限制和市场订单的工作参数。然后,您可以组合设置并设置一些平均参数。不幸的是,我没有足够的时间来充分利用它,因此还有采取进一步行动的空间。

当然,请注意,它不是现成的EA,您只需在图表上启动即可享用。使用其他类型的订单测试模拟,然后组合设置并重复这两个测试周期,直到EA显示可靠的交易结果。可能可以引入一些过滤器或自行调整算法。从测试中可以看出,进一步的改进是可能的。因此,您可以使用附加的程序并对其进行优化,以期获得稳定的结果。另外,我没有设法为更高的时间范围找到合适的设置。 EA在M5上效果最好,但是也许您可以找到其他时间表。另外,我没有时间检查货币对在其他货币对上的表现。但是,通常,这种扁平线意味着EA也应在其他货币对上运行。如果有时间,我将尝试继续完善EA。在撰写本文时,我发现了EA中的一些缺陷和错误,因此仍有许多工作要做。


结论

模拟器已经证明了对该分析方法的良好期望。获得第一个结果之后,就该考虑如何改进它们,如何使算法现代化以及使其变得更好,更快和更具可变性。这种方法的最大优点是最大程度的简化。我不是在讨论逻辑实现,而是从物理角度讲这种方法的基本逻辑。

我们不能考虑所有影响价格变动的因素。但是,即使至少有一个这样的因素(即使我们不能可靠地描述它),即使它的代码描述不准确也会产生某些信号。这些信号可能不是很高的质量,但是它们足以从该想法中产生一些收益。不要试图找到理想的公式,尽管这是不可能的,因为您永远无法考虑影响市场的所有因素。

而且,您不必完全使用我的方法。本文的目的是利用市场的某些物理原理,我认为至少部分描述了市场,并编写了可以证明这一想法的EA交易。结果,我开发了一个EA交易,它表明这些假设可以作为工作系统的基础。

还应考虑到代码具有较小和较大的缺陷和错误的事实。即使以这种形式,EA也可以工作。您应该只对其进行优化。在下一篇文章中,我将介绍另一种类型的多资产市场分析,它更简单,更有效并且为大家所熟知。同样,我们将创建一个EA交易。

由MetaQuotes Software Corp.从俄语翻译而来。
来源文章: //www.tbxfkj.com/ru/articles/8411

附加的文件 |
模拟.zip (27.31 KB)
神经网络变得简单(第9部分):记录工作 神经网络变得简单(第9部分):记录工作

我们已经走了很长一段路,并且库中的代码越来越大。这使得难以跟踪所有连接和依赖性。因此,我建议为先前创建的代码创建文档,并使其随每个新步骤更新。正确准备的文档将帮助我们看到工作的完整性。

开发自适应算法(第一部分):找到基本模式 开发自适应算法(第一部分):找到基本模式

在接下来的系列文章中,我将演示考虑大多数市场因素的自适应算法的开发,并展示如何将这些情况系统化,在逻辑上进行描述并在您的交易活动中加以考虑。我将以一个非常简单的算法开始,该算法将逐步掌握理论并发展成为一个非常复杂的项目。

使用CatBoost算法在外汇市场中查找季节性模式 使用CatBoost算法在外汇市场中查找季节性模式

本文考虑了使用时间过滤器创建机器学习模型,并讨论了这种方法的有效性。现在,只需指示模型在一周中特定日期的特定时间进行交易,就可以消除人为因素。模式搜索可以通过单独的算法提供。

蛮力模式搜索(第三部分):新视野 蛮力模式搜索(第三部分):新视野

本文提供了蛮力话题的延续,并将市场分析的新机会引入了程序算法,从而加快了分析速度并提高了结果质量。新增加的功能可在此方法中以最高质量查看全局模式。