English Русский Português
preview
无需真实期权的期权交易(第二部分):实盘中的应用

无需真实期权的期权交易(第二部分):实盘中的应用

MetaTrader 5示例 |
30 8
Dmitriy Skub
Dmitriy Skub

引言

在本系列的第一部分中,我们简要介绍了期权这一交易工具,以及它的功能、优势和劣势。我们提出了利用标的资产来模拟期权的理论,并在MQL5中进行了实践实现。现在,是时候在真实的市场交易中实际运用期权了。 

为此,我们需要创建一个EA,该EA将把期权模拟的层级映射为标的资产上的实际订单和持仓,并持续对由此产生的总持仓进行再平衡。


在实盘交易中的应用

首先,我们来看看在交易中可以使用哪些策略。在这里,我们仅探讨投机性策略。让我们从最简单的策略开始——买入/卖出单一期权。为此,我们将创建一个包含所有可能期权的表格。

简单的交易策略及其使用条件

买入看涨期权(Long Call)

  • 思路:买入看涨期权。 
  • 条件:如果确信标的资产价格将会上涨。
  • 利润:无上限。
  • 风险:购买期权所支付的权利金(在模拟中不存在此项)。

买入看跌期权(Long Put)

  • 思路:预期标的资产价格下跌而买入看跌期权。
  • 条件:如果确信标的资产价格将会下跌
  • 利润:无上限。
  • 风险:购买期权所支付的权利金(在模拟中不存在此项)。

卖出看涨期权 (Short Call)

  • 思路:卖出看涨期权,预期标的资产价格不会上涨,但也不一定下跌。
  • 条件:如果确信标的资产价格不会上涨
  • 利润:期权买方支付的权利金(在模拟模型中不存在此项)。
  • 风险:无上限。

卖出看跌期权 (Short Put)

  • 思路:卖出看跌期权,预期标的资产价格不会下跌,但也不一定上涨。
  • 条件:如果确信标的资产价格不会下跌
  • 利润:期权买方支付的权利金(在模拟模型中不存在此项)。
  • 风险:无上限。

注意事项:

  • 在模拟中卖出单一期权意义不大,因为模拟模型不涉及权利金。但是,为了进一步构建期权组合结构(按股票市场术语,也可称为期权投资组合),应当实现所有的期权类型。
  • 在购买模拟的单一期权时,自然不需要支付权利金。但是,在对投资组合进行再平衡时,可能会“累积”一定的亏损(可以将其视为支付权利金的等价物)。其大小取决于标的资产价格的具体变动以及持仓时间的长短。总体而言,这种亏损与权利金是相当的。


我们正在开发一个EA,用于实现交易策略。

TOptionBase 基础类以及 OptionLongCallOptionLongPutOptionShortCallOptionShortPut 等期权类保持不变(详见本系列的上一篇文章)。现在,让我们添加一个期权组合的基础类,这将允许我们在后续创建任意复杂度的期权组合。

这个 TOptionConstructionBase 类如下所示。我们让它继承自 MQL5 标准库中的 CList类。为了能够访问 CList,我们需要在代码开头添加以下代码行:

#include    <Arrays\List.mqh>

这将允许我们操作期权列表,以获取所需的组合的总体特征。那么,让我们来看看这个期权组合类:

// =====================================================================
//  Base class of the option construction - derived from 'CList':
// =====================================================================
class TOptionConstructionBase : public CList
{
protected:
  ENUM_OPTION_CONSTRUCTION    type_enum;
  double    total_delta;
  bool      is_option_construction_inited_Flag;

public:
  // ---------------------------------------------------------------------
  //  Destructor:
  // ---------------------------------------------------------------------
  ~TOptionConstructionBase()
  {
    this.Clear();
  }
  // ---------------------------------------------------------------------
  //  Constructor:
  // ---------------------------------------------------------------------
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION _type_enum)
  :
  type_enum(_type_enum),
  total_delta(0.0),
  is_option_construction_inited_Flag(false),
  CList()
  {
    this.FreeMode(true);
  }
  // ---------------------------------------------------------------------
  //  Get the value of the previously calculated normalized delta:
  // ---------------------------------------------------------------------
  double GetOptionConstructionDelta()
  {
    return(this.total_delta);
  }
  // ---------------------------------------------------------------------
  //  Get the value of the general initialization flag of the option construction:
  // ---------------------------------------------------------------------
  bool IsOptionConstructionInited()
  {
    return(this.is_option_construction_inited_Flag);
  }
  // ---------------------------------------------------------------------
  //  Set the delta normalization range for the central strike:
  // ---------------------------------------------------------------------
  void SetOptionConstructionRange(const double& _strike[], const double& _norm_price[])
  {
    this.is_option_construction_inited_Flag = true;
    if(this.Total() > 0)
    {
      int    i = 0;
      TOptionBase* curr_option = this.GetFirstNode();
      while(curr_option != NULL)
      {
        curr_option.SetRange(_strike[i], _norm_price[i]);
        if(curr_option.IsRangeInited() == true)
        {
          this.is_option_construction_inited_Flag = this.is_option_construction_inited_Flag && true;
        }
        else
        {
          this.is_option_construction_inited_Flag = false;
        }
        curr_option = this.GetNextNode();
        i++;
      }
    }
  }
  // ---------------------------------------------------------------------
  //  Delta update iterator:
  // ---------------------------------------------------------------------
  double UpdateOptionConstructionDelta(const double _price)
  {
    this.total_delta = 0.0;
    if(this.Total() > 0)
    {
      TOptionBase* curr_option = this.GetFirstNode();
      while(curr_option != NULL)
      {
        this.total_delta += curr_option.UpdateDelta(_price);
        curr_option = this.GetNextNode();
      }
    }

    return(this.total_delta);
  }
  // ---------------------------------------------------------------------
  //  Create an option construction:
  // ---------------------------------------------------------------------
  virtual void CreateOptionConstruction(const double _k, const double _s, const int _digits) = 0;
};
// ---------------------------------------------------------------------

让我们来仔细研究一下它。正如我们所见,在所展示代码的最底部声明了 CreateOptionConstruction 抽象方法,因此该基类本身是一个抽象类。该方法负责创建期权组合,并将在派生类中进行具体定义。该方法接收 _k、_s 和 _digits 三个参数。前两个参数是用于模拟期权的 Sigmoid 函数中的 K 值和 S 值。最后一个参数是标的资产的小数位数。

此外,我们还为 ENUM_OPTION_CONSTRUCTION(期权组合类型)实现了一个枚举。在当前阶段,它看起来如下所示:

// ---------------------------------------------------------------------
//  Option construction:
// ---------------------------------------------------------------------
enum ENUM_OPTION_CONSTRUCTION
{
  ENUM_OPTION_CONSTRUCTION_RISING = 0,                                // Base Active Rising - Long CALL
  ENUM_OPTION_CONSTRUCTION_FALLING = 1,                               // Base Active Falling - Long PUT
  ENUM_OPTION_CONSTRUCTION_NOT_RISING = 2,                            // Base Active NOT Rising - Short CALL
  ENUM_OPTION_CONSTRUCTION_NOT_FALLING = 3,                           // Base Active NOT Falling - Short PUT
};
// ---------------------------------------------------------------------

在未来,我们将向该枚举中添加更复杂的组合及新类型。在创建对象时,该类型会作为参数传递给类的构造函数。

SetOptionConstructionRange 方法(const double& _strike[], const double& _norm_price[])允许为组合中包含的每个期权设置中心行权价的 Delta 归一化范围。行权价和归一化范围的参数以数组引用的形式传入,这些数组包含相应的值。这些数组的维度(大小)必须等于该期权组合中期权的数量。

对于上述组合,该维度始终等于 1。在本次测试展示中,并未执行维度检查,但在用于实盘交易的正式版本中,可以很容易地将其添加进去。由于期权组合在初始化时就已经确定,因此数组的维度(实际上就是期权的数量)是预先已知的。

此外,基类还定义了 UpdateOptionConstructionDelta 方法(const double _price),用于更新期权组合的总 Delta,并返回计算出的总 Delta 值。该方法的输入参数是标的资产的价格。该方法利用 CList 类的方法来遍历列表中的所有元素。

接下来,我们从基类派生出真实的期权组合类。由于所有功能都已包含在基类中,派生类的结构相当简单:

// =====================================================================
//  Class of option construction of 'Base Active Rising' type:
// =====================================================================
class BaseActiveRisingOptionConstruction : public TOptionConstructionBase
{
public:
  // ---------------------------------------------------------------------
  //  Constructor:
  // ---------------------------------------------------------------------
  BaseActiveRisingOptionConstruction()
  :
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION_RISING)
  {
  }
  // ---------------------------------------------------------------------
  //  Create an option construction:
  // ---------------------------------------------------------------------
  virtual void    CreateOptionConstruction(const double _k, const double _s, const int _digits) override
  {
    this.Add(new OptionLongCall(_k, _s, _digits));
  }
};

// =====================================================================
//  Class of option construction of 'Base Active Falling' type:
// =====================================================================
class BaseActiveFallingOptionConstruction : public TOptionConstructionBase
{
public:
  // ---------------------------------------------------------------------
  //  Constructor:
  // ---------------------------------------------------------------------
  BaseActiveFallingOptionConstruction()
  :
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION_FALLING)
  {
  }
  // ---------------------------------------------------------------------
  //  Create an option construction:
  // ---------------------------------------------------------------------
  virtual void    CreateOptionConstruction(const double _k, const double _s, const int _digits) override
  {
    this.Add(new OptionLongPut(_k, _s, _digits));
  }
};

// =====================================================================
//  Class of option construction of 'Base Active NOT Rising' type:
// =====================================================================
class BaseActiveNotRisingOptionConstruction : public TOptionConstructionBase
{
public:
  // ---------------------------------------------------------------------
  //  Constructor:
  // ---------------------------------------------------------------------
  BaseActiveNotRisingOptionConstruction()
  :
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION_NOT_RISING)
  {
  }
  // ---------------------------------------------------------------------
  //  Create an option construction:
  // ---------------------------------------------------------------------
  virtual void    CreateOptionConstruction(const double _k, const double _s, const int _digits) override
  {
    this.Add(new OptionShortCall(_k, _s, _digits));
  }
};

// =====================================================================
//  Class of option construction of 'Base Active NOT Falling' type:
// =====================================================================
class BaseActiveNotFallingOptionConstruction : public TOptionConstructionBase
{
public:
  // ---------------------------------------------------------------------
  //  Constructor:
  // ---------------------------------------------------------------------
  BaseActiveNotFallingOptionConstruction()
  :
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION_NOT_FALLING)
  {
  }
  // ---------------------------------------------------------------------
  //  Create an option construction:
  // ---------------------------------------------------------------------
  virtual void    CreateOptionConstruction(const double _k, const double _s, const int _digits) override
  {
    this.Add(new OptionShortPut(_k, _s, _digits));
  }
};

// ---------------------------------------------------------------------

派生类中唯一需要做的就是定义 CreateOptionConstruction 方法。在该方法中,我们会创建所需的期权(或期权组)对象,并通过调用 CList::Add 方法将创建的对象添加到列表中。

这些类位于本文附带的 OptionEmulatorA2.mqh 文件中。

输入参数

现在,让我们继续实现用于通过真实持仓管理执行模拟的EA。首先,让我们添加一个枚举,用于定义EA的整体(通用)状态或交易状态:

// ---------------------------------------------------------------------
//  Current trading status:
// ---------------------------------------------------------------------
enum ENUM_TRADE_MODE_STATE
{
  ENUM_TRADE_MODE_STARTED,                                            // trading is ONGOING, positions are HANDLED
  ENUM_TRADE_MODE_STOPPED,                                            // trading is STOPPED, all positions are CLOSED
  ENUM_TRADE_MODE_PAUSED,                                             // trading is SUSPENDED by the operator, existing positions are NOT HANDLED
  ENUM_TRADE_MODE_WAITING,                                            // trading is AWAITING automatic renewal, existing positions are HANDLED, IF POSSIBLE
};
// ---------------------------------------------------------------------

在EA的初始版本中,将仅使用两种状态:交易停止和交易进行中。交易在EA初始化完成后启动,并在达到设定的到期时间后停止。我们将使用每日期权,且强制要求在新的一天开始前到期。 

向EA添加必要的外部参数:

// =====================================================================
//  Externally set parameters:
// =====================================================================
input ENUM_OPTION_CONSTRUCTION    OptionConstruction = ENUM_OPTION_CONSTRUCTION_RISING;  // Option Construction
input ulong     BaseMagic = 10000UL;                                  // Base Magic
input int       MinLotsMultiplier = 1;                                // Min Lots Multiplier
// ---------------------------------------------------------------------
input int       AddNewFromHours = 0;                                  // Add New Hours (0...23) From
input int       AddNewToHours = 24;                                   // Add New Hours (1...24) To
input int       ExpirationTimeHours = 24;                             // Expiration Time, Hours (1...24)
input int       ExpirationTimeMinutes = 0;                            // Expiration Time, Minutes (0...59)
// ---------------------------------------------------------------------
input double    ZeroDelta = 0.01;                                     // Zero Delta (0.01...0.1)
input string    ForceAutoExpirationTime = "23:50";                    // Force Auto Expiration Time (MT5 Server)
input int       ADRDaysNumber = 20;                                   // ADR Days Number
// ---------------------------------------------------------------------

外部参数说明:

  • BaseMagic —— “魔术号”(Magic Number)的基础值(在开仓时,会在此值上加上期权模拟层级编号乘以100的值);
  • MinLotsMultiplier —— 确定每个层级的持仓量时的最小手数乘数;
  • AddNewFromHours —— EA在一天内开始运行的时间,以小时为单位(0 到 23 小时);
  • AddNewToHours —— EA在一天内结束运行的时间,以小时为单位(1 到 24 小时);
  • ExpirationTimeHours —— 期权组合在一天内的到期时间,以小时为单位(1 到 24 小时);
  • ExpirationTimeMinutes —— 期权组合在一天内的到期时间,以分钟为单位(0 到 59 分钟);
  • ForceAutoExpirationTime —— EA强制自动到期的时间,格式为 "hh:mm";
  • ADRDaysNumber —— 用于计算历史波动参数的天数。

交易EA

以下是该交易EA中值得关注的几个函数:

//---------------------------------------------------------------------
//    Get normalized trading volume:
//---------------------------------------------------------------------
//  • the required lot at the input;
//  • normalized lot at the output;
//---------------------------------------------------------------------
double
NormalizeLots(const double _requied_lots)
{
  double    lots, koeff;
  int       nmbr;

  if(min_trade_volume_step > 0.0)
  {
    koeff = 1.0 / min_trade_volume_step;
    nmbr = (int)MathLog10(koeff);
  }
  else
  {
    koeff = 1.0 / min_trade_volume;
    nmbr = 2;
  }
  lots = MathFloor(_requied_lots * koeff) / koeff;

  //  Lot limit from below:
  if(lots < min_trade_volume)
  {
    lots = min_trade_volume;
  }

  //  Upper lot limit:
  if(lots > max_trade_volume)
  {
    lots = max_trade_volume;
  }

  lots = NormalizeDouble(lots, nmbr);
  return(lots);
}

之所以需要进行手数归一化,是因为在真实交易中,交易品种的交易量变化是离散的。此外,交易量的表示精度以及最小/最大交易量值都受到限制。上述 NormalizeLots 函数已将所有这些要求考虑在内。

// ---------------------------------------------------------------------
//    Normalize price considering the step of quote change:
// ---------------------------------------------------------------------
double
NormalizePrice(const double _price)
{
  //  Minimum step of change of quotes in points:
  double    min_price_step = NormalizeDouble(symbol_tick_size / Point(), 0 );

  double    norm_price = NormalizeDouble(NormalizeDouble((NormalizeDouble(_price / Point(), 0 )) / min_price_step, 0 ) * min_price_step * Point(), Digits());
  return(norm_price);
}
// ---------------------------------------------------------------------

在这里,我们使用了初始化期间获取的全局变量值:

double  min_trade_volume = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN);
double  max_trade_volume = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MAX);
double  min_trade_volume_step = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_STEP);
double  symbol_tick_size = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_SIZE);

交易 EA 的算法基于在 OnTick 函数中处理每一个新报价(Tick)。下面展示了一个简化的处理程序结构:

//    Handle a new tick (if all necessary conditions are met):
if(is_bars_loaded_Flag == true && is_adr_levels_calculated_Flag == true && option_construstion_Ptr.IsOptionConstructionInited() == true)
{
  if(SymbolInfoTick(Symbol(), tick) == true)
  {
    ask_option_construction_delta = option_construstion_Ptr.UpdateOptionConstructionDelta(tick.ask);
    bid_option_construction_delta = option_construstion_Ptr.UpdateOptionConstructionDelta(tick.bid);
    curr_option_construction_delta = option_construstion_Ptr.UpdateOptionConstructionDelta((tick.ask + tick.bid) / 2.0);

    if(is_first_ea_starting == true)
    {
      is_first_ea_starting = false;
Print("CurrDelta : ", DoubleToString(curr_option_construction_delta, 3), "  BidDelta : ", DoubleToString(bid_option_construction_delta, 3), "  AskDelta : ", DoubleToString(ask_option_construction_delta, 3));
    }

    //  Calculate the current REQUIRED POSITION VOLUME with a check to see if the option emulation level has changed:
    if(option_contruction_volume_Ptr.UpdateOptionLevel(curr_option_construction_delta, prev_option_level_value) == true)
    {
      //  Current sign of the option emulation level (+1/0/-1):
      live_option_level_sign = option_contruction_volume_Ptr.GetOptionLevelSign();
                
      //  Current value (modulo) of the option emulation level (0/1/2/3/4/5/6/7/8/9/10):
      live_option_level_value = option_contruction_volume_Ptr.GetOptionLevel();

      //  It is necessary to change the position volume - rebalance the option construction:
      if(live_option_level_value > 0)
      {
        live_position_lots_abs = NormalizeLots(live_option_level_value * min_trade_volume_step * MinLotsMultiplier);
      }
      else
      {
        live_position_lots_abs = 0.0;
      }

Print("#NEW LEVEL  Position Volume : ", DoubleToString(live_option_level_value * live_option_level_sign * MinLotsMultiplier, 1), "  CurrDelta : ", DoubleToString(curr_option_construction_delta, 3), "  Levels Prev/Live: ", prev_option_level_value, "/", live_option_level_value);

      //  If we are in 'STARTED' mode, adjust the total volume of virtual and real positions:
      if(current_trade_mode_state == ENUM_TRADE_MODE_STARTED)
      {
        //  If the value of the option emulation LEVEL has INCREASED, then positions need to be added to new levels:
        if(live_option_level_value > prev_option_level_value)
        {
          //  BUY positions:
          if(live_option_level_sign == 1)
          {
            //  If the interval for placing new orders has not yet passed:
            if(CheckAddingNew(tick.time) == true)
            {
              //  Set real orders at new levels:
              OpenBuyLevels(live_option_level_value, live_option_level_value - prev_option_level_value);
            }
          }
          //  SELL positions:
          else if(live_option_level_sign == -1)
          {
            //  If trading is allowed:
            if(is_trade_allowed_Flag == true)
            {
              //  If the interval for placing new orders has not yet passed:
              if(CheckAddingNew(tick.time) == true)
              {
                //  Set real orders at new levels:
                OpenSellLevels(live_option_level_value, live_option_level_value - prev_option_level_value);
              }
            }
          }
          prev_option_level_value = live_option_level_value;
          prev_option_level_sign = live_option_level_sign;
        }
        //  If the value of the option emulation LEVEL has DECREASED, then it is necessary to close some or all positions at the previous levels:
        else if(live_option_level_value < prev_option_level_value)
        {
          //  BUY positions:
          if(live_option_level_sign == 1)
          {
            //  If trading is allowed:
            if(is_trade_allowed_Flag == true)
            {
              for(int curr_level = prev_option_level_value; curr_level > live_option_level_value; curr_level--)
              {
                CloseLevelPositions(Symbol(), POSITION_TYPE_BUY, curr_level);
              }
            }
          }
          //  SELL positions:
          else if(live_option_level_sign == -1)
          {
            //  If trading is allowed:
            if(is_trade_allowed_Flag == true)
            {
              for(int curr_level = prev_option_level_value; curr_level > live_option_level_value; curr_level--)
              {
                CloseLevelPositions(Symbol(), POSITION_TYPE_SELL, curr_level);
              }
            }
          }
          //  The current value (modulo) of the delta level during option emulation has become ZERO (all positions should be closed):
          else  if(live_option_level_sign == 0)
          {
            //  If trading is allowed:
            if(is_trade_allowed_Flag == true)
            {
              if(prev_option_level_sign == 1)
              {
                for(int curr_level = prev_option_level_value; curr_level > live_option_level_value; curr_level--)
                {
                  CloseLevelPositions(Symbol(), POSITION_TYPE_BUY, curr_level);
                }
              }
              else if(prev_option_level_sign == -1)
              {
                for(int curr_level = prev_option_level_value; curr_level > live_option_level_value; curr_level--)
                {
                  CloseLevelPositions(Symbol(), POSITION_TYPE_SELL, curr_level);
                }
              }
            }
            live_position_lots_abs = 0.0;
            live_option_level_sign = 0;
          }
        }
      }
      prev_option_level_value = live_option_level_value;
      prev_option_level_sign = live_option_level_sign;      }
    }
  }
}

通过调用 UpdateOptionLevel 方法来跟踪期权模拟层级的变化。如果层级发生了变化,该方法将返回 'true'。在这里,我们将当前的期权模拟层级值与上一个报价(前一个 Tick)时的值进行比较。

如果需要再平衡持仓,则检查期权模拟层级是增加了还是减少了。如果层级增加,则需要加仓。如果层级减少,则需要平掉部分仓位。如果模拟层级变为零,我们将平掉所有未平仓位。通过这种方式,对总持仓进行再平衡。

请注意,我们在计算期权组合的当前 Delta 时,取的是 Bid(卖价)和 Ask(买价)之间的平均值作为价格。这有助于减少 Delta 变化对点差变化的依赖。EA 的完整文本可以在本文附带的文件中找到。

在开仓和平仓时使用市价单。这样做是为了简化对 EA 工作的验证(保证订单会被执行)。未来,建议(并且需要实施)切换到使用限价单开仓。这将通过消除入场时的点差来降低佣金成本并改善交易结果。

模拟测试与实盘交易

假设我们判断 EURUSD 价格在当天的主要走势是向上的。我们将期权组合类型设置为 OptionConstruction = ENUM_OPTION_CONSTRUCTION_RISING。下图展示了模拟"标的资产上涨 - 买入看涨期权"组合的 EA 示例:图.1 — 从一天开始时的全景,图.2 — 放大的交易区域。触发了 1 到 9 级模拟层级。在 EA 开始运行时进行了层级再平衡:

图 1. "标的资产上涨 - 买入看涨期权"组合运行中 — 概览

图 2. "标的资产上涨 - 买入看涨期权"组合运行中(放大视图)


图 3. 模拟"标的资产上涨 - 买入看涨期权"组合期间的当前持仓状态

 

图 4. 模拟"标的资产上涨 - 买入看涨期权"组合期间再平衡的结果,以交易历史中的订单形式展示

现在假设第二天我们判断价格将反转下跌。将 OptionConstruction 期权组合类型设置为ENUM_OPTION_CONSTRUCTION_FALLING。这一次运气不在我们这边——价格在一天结束时反转并对我们不利,我们遭受了一些损失。图 5. 展示了该期权组合的发展情况。开仓了第 1 到第 5 级模拟层级。由于再平衡而记录的亏损为 -5.77 美元(见图 6)。

图 5. "标的资产下跌 - 买入看跌期权"组合运行中 — 概览


图 6. 模拟"标的资产上涨 - 买入看跌期权"组合期间再平衡的结果,以交易历史中的订单形式展示

持仓的最大总手数可以达到 0.1 = 10 个层级 * 0.01 — 这是在最小手数乘数等于 1 时的期权组合目标手数。从图 4 可以看出,我们在第一种情况下因再平衡期权组合而遭受了 -2.39 美元的固定亏损,在第二种情况下(见图 6)亏损了 -5.77 美元。这类似于购买期权时支付的权利金。正如 EA 参数 ForceAutoExpirationTime = "23:50" 所指定的那样,在 23:50,期权组合到期,在第一种情况下锁定了利润。很明显,交易结果取决于具体的市场情况和我们的操作。


结论

我们已经探讨了模拟给定期权组合的 EA 的实际实现。我们已经验证了实践与本系列第一篇文章中介绍的理论原则相符。在下一篇文章中,我们将探讨具有真正实用价值的期权策略的实现。它们被专业的期权交易员所使用。

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/18363

附加的文件 |
最近评论 | 前往讨论 (8)
prostotrader
prostotrader | 19 10月 2025 在 08:45

大家好!

这当然很有意思。

但是!

您:

-->假设我们认为,当天欧元兑美元(EURUSD)的价格将 主要呈上涨趋势……

--->现在假设第二天我们又认为价格会反转并下跌……

这又成了“抛硬币”式的操作,最终不可避免地会导致本金血本无归。

德米特里,你付出了巨大努力,但这并不能带来稳定的收益。

补充

我很久以前做过一个实验。

我选取了M1K线图的一年周期,起初在K线开盘时买入,收盘时卖出,如此持续了一整年。

结果亏损惨重。

随后,我将买入操作改为卖出,卖出操作改为买入,同样持续了一整年。结果……

又亏损惨重! :)

补充

交易涵盖MOEX所有股票期货的对冲投资组合。

风险 +85/-15 %

之所以设定-15%的风险,是因为可能突然宣布派发股息

9天前

今天

正在加紧工作,以缩小-15%的跌幅

Dmitriy Skub
Dmitriy Skub | 19 10月 2025 在 09:44

所以,没有哪种市场策略能保证稳定的收益。包括你的策略在内,尤其是在当今这种谁都不知道明天会发生什么的情况下。因此,只有在日内交易中才能赚点钱,且不持仓过夜——这只是我个人的看法。

你的HFT主要利润来自股票及其期货的组合,我理解得对吗?

prostotrader
prostotrader | 19 10月 2025 在 09:50
Dmitriy Skub #:

所以,没有哪种市场策略能保证稳定的收益。包括你的策略在内,尤其是在当今这种谁都不知道明天会发生什么的情况下。因此,只有在日内交易中才能赚点钱,不要持仓过夜,这只是我个人的看法。

你的HFT主要利润来自股票及其期货的组合,我这样理解对吗?

不,由于Finam不提供已购股票的折扣,我现在没有使用这个“黄金”的100%盈利策略

目前我仅交易期货,并用其 对MOEH指数中的所有股票进行对冲

--->因此,没有任何市场策略能保证稳定的收益。

只是你还没发现它们罢了……

没有人,包括我在内,会告诉你这些策略。

已添加

任何对冲策略都应带来稳定的收益。

有5个关键因素

1. 风险

2. 正确实施

3. 交易指令的执行速度

4. 交易者的贪婪(有人觉得年化50%就够了,而有人觉得500%还不够——正因如此,99%的交易者才会亏光……)

5. 仅通过交易机器人进行交易(必须完全排除人为因素)
Dmitriy Skub
Dmitriy Skub | 19 10月 2025 在 12:36

这里需要了解什么?

您等待股票与期货之间出现最大背离(从统计学意义上讲),在此时买入股票,卖出期货。然后等待到期日。如果资金充足,这完全是一种可行的策略。不过,该策略本身也存在风险。

以前,您会在日内(或数日内)买入/卖出背离/趋同,可能只平仓其中一笔头寸。

为什么现在不这么做了——看来是流动性不足。

Sergey Chalyshev
Sergey Chalyshev | 19 10月 2025 在 21:06

期权和期权策略本身并不会带来任何收益。这与外汇交易一样,胜率是五五开。其数学原理相同,遵循正态概率分布

只有将期权与期货或股票结合使用时,期权才能带来(无风险)收益。

交易策略 交易策略
各种交易策略的分类都是任意的,下面这种分类强调从交易的基本概念上分类。
利用机器学习研究分形市场结构导论 利用机器学习研究分形市场结构导论
本文尝试从自相似分形结构的角度来研究金融时间序列。鉴于我们有众多类比证实市场报价可作为自相似分形来考虑,这使我们能够思考此类结构的预测视野。
新手在交易中的10个基本错误 新手在交易中的10个基本错误
新手在交易中会犯的10个基本错误: 在市场刚开始时交易, 获利时不适当地仓促, 在损失的时候追加投资, 从最好的仓位开始平仓, 翻本心理, 最优越的仓位, 用永远买进的规则进行交易, 在第一天就平掉获利的仓位,当发出建一个相反的仓位警示时平仓, 犹豫。
市场模拟(第 24 部分):SQL 入门(七) 市场模拟(第 24 部分):SQL 入门(七)
在上一篇文章中,我们完成了对 SQL 的必要介绍。而且,在我看来,我们已经恰当地阐明了我们想要展示和解释的关于 SQL 的内容。这样做是为了让任何前来查看正在构建的市场回放/模拟系统的人,至少能对那里可能发生的情况有所了解。关键在于,对于那些 SQL 能完美处理的事情,编程是没有意义的。