Русский
preview
Operando opções sem opções (Parte 2): Uso em operações reais

Operando opções sem opções (Parte 2): Uso em operações reais

MetaTrader 5Exemplos |
30 8
Dmitriy Skub
Dmitriy Skub

Introdução

Na primeira parte da série, descrevemos brevemente a opção como instrumento de negociação, suas possibilidades de uso, vantagens e desvantagens. Desenvolvemos a teoria e a implementação prática, em MQL5, de um método para emular uma opção usando o ativo subjacente. Chegou a hora de testar as opções na prática, isto é, usá-las nas operações de mercado. 

Para isso, precisamos criar um EA que se encarregue de mapear os níveis de emulação da opção para ordens e posições reais no ativo subjacente, além de rebalancear continuamente a posição total resultante.


Uso em operações reais

Primeiro, vamos analisar quais estratégias podemos usar no trading. Aqui consideramos apenas estratégias especulativas. Vamos começar pelas mais simples: compra/venda de opções individuais. Para isso, montaremos uma tabela com todas as variantes possíveis.

Estratégias simples de trading e quando utilizá-las

Compra de call, Long Call

  • Ideia: compra de uma opção call 
  • Condição: quando há convicção de alta no preço do ativo subjacente
  • Lucro: ilimitado
  • Risco: prêmio pago pela opção (inexistente na emulação)

Compra de put, Long Put

  • Ideia: compra de uma opção put na expectativa de queda do preço do ativo subjacente
  • Condição: quando há convicção de queda no preço do ativo subjacente
  • Lucro: ilimitado
  • Risco: prêmio pago pela opção (inexistente na emulação)

Venda de call, Short Call

  • Ideia: venda de uma opção call na expectativa de que o preço do ativo subjacente não suba, embora não precise necessariamente cair
  • Condição: quando há convicção de que o preço do ativo subjacente não subirá
  • Lucro: prêmio pago pelo comprador da opção (inexistente na emulação)
  • Risco: ilimitado

Venda de put, Short Put

  • Ideia: venda de uma opção put na expectativa de que o preço do ativo subjacente não caia, embora não precise necessariamente subir
  • Condição: quando há convicção de que o preço do ativo subjacente não cairá
  • Lucro: prêmio pago pelo comprador da opção (inexistente na emulação)
  • Risco: ilimitado

Observações:

  • A venda de opções individuais emuladas não faz muito sentido, pois não há prêmio nessa operação. Mas, para a criação posterior de estruturas de opções (na terminologia do mercado de valores mobiliários, carteiras de opções), é necessário implementar todas as variantes.
  • Na compra de opções individuais emuladas, naturalmente, o prêmio não é pago. Mas, durante o rebalanceamento da carteira, pode acabar se acumulando certo prejuízo (podemos considerá-lo equivalente ao pagamento do prêmio). Seu valor depende da variação específica do preço do ativo subjacente e do tempo de permanência nas posições. Em geral, esse prejuízo é comparável ao prêmio.


Codificando um EA para implementar a estratégia de trading

A classe base TOptionBase e as classes de opções OptionLongCall, OptionLongPut, OptionShortCall, OptionShortPut permanecem inalteradas (veja o artigo anterior da série). Agora adicionaremos a classe base de uma estrutura de opções, que futuramente permitirá criar estruturas de opções de qualquer complexidade.

Essa classe TOptionConstructionBase é mostrada abaixo. Essa classe herda da classe padrão CList, incluída no conjunto de bibliotecas MQL5. Para acessar CList, é preciso adicionar a linha no início:

#include    <Arrays\List.mqh>

Isso permitirá manipular listas de opções para obter a característica consolidada da carteira necessária. Portanto, apresentamos a classe da estrutura de opções:

// =====================================================================
//  Базовый класс опционной конструкции - порожден от 'CList':
// =====================================================================
class TOptionConstructionBase : public CList
{
protected:
  ENUM_OPTION_CONSTRUCTION    type_enum;
  double    total_delta;
  bool      is_option_construction_inited_Flag;

public:
  // ---------------------------------------------------------------------
  //  Деструктор:
  // ---------------------------------------------------------------------
  ~TOptionConstructionBase()
  {
    this.Clear();
  }
  // ---------------------------------------------------------------------
  //  Конструктор:
  // ---------------------------------------------------------------------
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION _type_enum)
  :
  type_enum(_type_enum),
  total_delta(0.0),
  is_option_construction_inited_Flag(false),
  CList()
  {
    this.FreeMode(true);
  }
  // ---------------------------------------------------------------------
  //  Получить значение вычисленной ранее нормированной дельты:
  // ---------------------------------------------------------------------
  double GetOptionConstructionDelta()
  {
    return(this.total_delta);
  }
  // ---------------------------------------------------------------------
  //  Получить значение флага общей инициализации опционной конструкции:
  // ---------------------------------------------------------------------
  bool IsOptionConstructionInited()
  {
    return(this.is_option_construction_inited_Flag);
  }
  // ---------------------------------------------------------------------
  //  Установить диапазон нормировки дельты для центрального страйка:
  // ---------------------------------------------------------------------
  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++;
      }
    }
  }
  // ---------------------------------------------------------------------
  //  Итератор обновления дельты:
  // ---------------------------------------------------------------------
  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);
  }
  // ---------------------------------------------------------------------
  //  Создание опционной конструкции:
  // ---------------------------------------------------------------------
  virtual void CreateOptionConstruction(const double _k, const double _s, const int _digits) = 0;
};
// ---------------------------------------------------------------------

Vamos examiná-la com mais detalhes. Como podemos ver, no final do código apresentado aparece a declaração do método abstrato CreateOptionConstruction, portanto a própria classe base também é abstrata. Esse método cria diretamente a estrutura de opções e será definido nas classes derivadas. O método recebe os parâmetros _k, _s e _digits. Os dois primeiros são os valores K e S na função sigmoide que emula a opção. O último é o número de casas decimais do ativo subjacente.

Também foi adicionada a enumeração ENUM_OPTION_CONSTRUCTION para o tipo de estrutura de opções. Nesta etapa, ela tem a seguinte forma:

// ---------------------------------------------------------------------
//  Опционная конструкция:
// ---------------------------------------------------------------------
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
};
// ---------------------------------------------------------------------

Mais adiante, adicionaremos estruturas mais complexas e novos tipos à enumeração. Esse tipo é passado como parâmetro ao construtor da classe durante a criação do objeto.

O método SetOptionConstructionRange(const double& _strike[], const double& _norm_price[]) permite definir o intervalo de normalização do delta para o strike central em cada uma das opções que compõem a estrutura. Os parâmetros dos valores de strike e dos intervalos de normalização são passados como referências a arrays nos quais os respectivos valores devem ser registrados. O tamanho dos arrays deve ser igual ao número de opções na estrutura de opções.

Para as estruturas listadas acima, a dimensão é sempre igual a um. Nesta versão de teste, não se verifica se o tamanho está correto, mas é fácil adicioná-la na versão de produção para operações reais. Como a estrutura de opções já é definida de início, a dimensão dos arrays (na prática, o número de opções) é conhecida de antemão.

Além disso, na classe base é definido um método para atualizar o delta agregado da estrutura de opções, UpdateOptionConstructionDelta(const double _price), que retorna o delta agregado calculado. O parâmetro de entrada do método é o preço do ativo subjacente. Esse método usa os métodos da classe CList para iterar por todos os elementos da lista.

Em seguida, derivamos da classe base as estruturas de opções concretas. Como toda a funcionalidade está contida na classe base, as classes derivadas têm uma estrutura bastante simples:

// =====================================================================
//  Класс опционной конструкции типа 'Base Active Rising':
// =====================================================================
class BaseActiveRisingOptionConstruction : public TOptionConstructionBase
{
public:
  // ---------------------------------------------------------------------
  //  Конструктор:
  // ---------------------------------------------------------------------
  BaseActiveRisingOptionConstruction()
  :
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION_RISING)
  {
  }
  // ---------------------------------------------------------------------
  //  Создание опционной конструкции:
  // ---------------------------------------------------------------------
  virtual void    CreateOptionConstruction(const double _k, const double _s, const int _digits) override
  {
    this.Add(new OptionLongCall(_k, _s, _digits));
  }
};

// =====================================================================
//  Класс опционной конструкции типа 'Base Active Falling ':
// =====================================================================
class BaseActiveFallingOptionConstruction : public TOptionConstructionBase
{
public:
  // ---------------------------------------------------------------------
  //  Конструктор:
  // ---------------------------------------------------------------------
  BaseActiveFallingOptionConstruction()
  :
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION_FALLING)
  {
  }
  // ---------------------------------------------------------------------
  //  Создание опционной конструкции:
  // ---------------------------------------------------------------------
  virtual void    CreateOptionConstruction(const double _k, const double _s, const int _digits) override
  {
    this.Add(new OptionLongPut(_k, _s, _digits));
  }
};

// =====================================================================
//  Класс опционной конструкции типа 'Base Active NOT Rising':
// =====================================================================
class BaseActiveNotRisingOptionConstruction : public TOptionConstructionBase
{
public:
  // ---------------------------------------------------------------------
  //  Конструктор:
  // ---------------------------------------------------------------------
  BaseActiveNotRisingOptionConstruction()
  :
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION_NOT_RISING)
  {
  }
  // ---------------------------------------------------------------------
  //  Создание опционной конструкции:
  // ---------------------------------------------------------------------
  virtual void    CreateOptionConstruction(const double _k, const double _s, const int _digits) override
  {
    this.Add(new OptionShortCall(_k, _s, _digits));
  }
};

// =====================================================================
//  Класс опционной конструкции типа 'Base Active NOT Falling':
// =====================================================================
class BaseActiveNotFallingOptionConstruction : public TOptionConstructionBase
{
public:
  // ---------------------------------------------------------------------
  //  Конструктор:
  // ---------------------------------------------------------------------
  BaseActiveNotFallingOptionConstruction()
  :
  TOptionConstructionBase(ENUM_OPTION_CONSTRUCTION_NOT_FALLING)
  {
  }
  // ---------------------------------------------------------------------
  //  Создание опционной конструкции:
  // ---------------------------------------------------------------------
  virtual void    CreateOptionConstruction(const double _k, const double _s, const int _digits) override
  {
    this.Add(new OptionShortPut(_k, _s, _digits));
  }
};

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

Tudo o que precisa ser feito na classe descendente é definir o método que cria a estrutura de opções CreateOptionConstruction. Nesse método, criamos o objeto da opção necessária (ou de um grupo de opções) e adicionamos o objeto criado à lista, chamando o método CList::Add.

Essas classes estão no arquivo "OptionEmulatorA2.mqh", que acompanha este artigo.

Parâmetros de entrada

Agora vamos iniciar a implementação do próprio EA, que fará a emulação por meio da gestão de posições reais. Primeiro, adicionaremos uma enumeração que definirá o estado global (geral) do EA ou o estado do trading:

// ---------------------------------------------------------------------
//  Текущее состояние торговли:
// ---------------------------------------------------------------------
enum ENUM_TRADE_MODE_STATE
{
  ENUM_TRADE_MODE_STARTED,                                            // торговля ИДЕТ, позиции ОБСЛУЖИВАЮТСЯ
  ENUM_TRADE_MODE_STOPPED,                                            // торговля ОСТАНОВЛЕНА, все позиции ЗАКРЫТЫ
  ENUM_TRADE_MODE_PAUSED,                                             // торговля ПРИОСТАНОВЛЕНА оператором, существующие позиции НЕ ОБСЛУЖИВАЮТСЯ
  ENUM_TRADE_MODE_WAITING,                                            // торговля ОЖИДАЕТ автоматического возобновления, существующие позиции ОБСЛУЖИВАЮТСЯ, ПРИ ВОЗМОЖНОСТИ
};
// ---------------------------------------------------------------------

Na versão inicial do EA, serão usados apenas dois estados: trading interrompido e trading em andamento. O trading é iniciado no arranque do EA, após a conclusão da sua inicialização, e é interrompido depois que o horário de expiração é atingido. Usaremos opções diárias com expiração obrigatória antes do início do próximo dia. 

Adicionaremos os parâmetros externos necessários ao EA:

// =====================================================================
//  Внешние задаваемые параметры:
// =====================================================================
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
// ---------------------------------------------------------------------

Parâmetros externos que podem levantar dúvidas:

  • BaseMagic: valor base do número "mágico" (ao abrir uma posição, é somado a ele o número do nível de emulação da opção, multiplicado por 100);
  • MinLotsMultiplier: multiplicador do lote mínimo ao determinar o volume da posição em cada um dos níveis;
  • AddNewFromHours: início da operação intradiária do EA, em horas (de 0 a 23 horas);
  • AddNewToHours: encerramento da operação intradiária do EA, em horas (de 1 a 24 horas);
  • ExpirationTimeHours: horário de expiração da estrutura de opções intradiário, em horas de 1 a 24;
  • ExpirationTimeMinutes: horário de expiração da estrutura de opções intradiário, em minutos de 0 a 59;
  • ForceAutoExpirationTime: horário de expiração incondicional e interrupção da operação do EA, no formato "hh:mm";
  • ADRDaysNumber: número de dias para calcular a volatilidade histórica HV.

EA de trading

As seguintes funções do EA de trading merecem atenção:

//---------------------------------------------------------------------
//    Получить нормализованный торговый объем:
//---------------------------------------------------------------------
//  • на входе требуемый лот;
//  • на выходе нормализованный лот;
//---------------------------------------------------------------------
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;

  //  Ограничение лота снизу:
  if(lots < min_trade_volume)
  {
    lots = min_trade_volume;
  }

  //  Ограничение лота сверху:
  if(lots > max_trade_volume)
  {
    lots = max_trade_volume;
  }

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

A normalização do lote é necessária porque, nas operações reais, os instrumentos permitem alterar o volume operado apenas em incrementos discretos. Além disso, o número de casas decimais na representação do volume e os valores mínimo/máximo do volume são limitados. Todos esses requisitos são levados em conta na função NormalizeLots apresentada acima.

// ---------------------------------------------------------------------
//    Нормализация цены с учетом шага изменения котировок:
// ---------------------------------------------------------------------
double
NormalizePrice(const double _price)
{
  //  Минимальный размер шага изменения котировок, пунктов:
  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);
}
// ---------------------------------------------------------------------

Aqui são usados os valores das variáveis globais obtidos durante a inicialização:

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);

O algoritmo de operação do EA se baseia no manipulador do evento de novo tick, OnTick. O esquema simplificado do manipulador é apresentado abaixo:

//    Обработка нового тика (если выполнены все необходимые условия):
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));
    }

    //  Расчитаем текущий ТРЕБУЕМЫЙ ОБЪЕМ ПОЗИЦИИ с проверкой, изменился ли уровень эмуляции опционов:
    if(option_contruction_volume_Ptr.UpdateOptionLevel(curr_option_construction_delta, prev_option_level_value) == true)
    {
      //  Текущий знак уровня эмуляции опционов (+1/0/-1):
      live_option_level_sign = option_contruction_volume_Ptr.GetOptionLevelSign();
                
      //  Текущее значение (по модулю) уровня эмуляции опционов (0/1/2/3/4/5/6/7/8/9/10):
      live_option_level_value = option_contruction_volume_Ptr.GetOptionLevel();

      //  Требуется изменить объем позиции - ребалансировать опционную конструкцию:
      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);

      //  Если находимся в режие 'STARTED', то скорректируем совокупный объем виртуальной и реальной позиций:
      if(current_trade_mode_state == ENUM_TRADE_MODE_STARTED)
      {
        //  Если значение УРОВНЯ эмуляции опционов УВЕЛИЧИЛОСЬ, значит надо добавить позиции на новые уровени:
        if(live_option_level_value > prev_option_level_value)
        {
          //  Позиции BUY:
          if(live_option_level_sign == 1)
          {
            //  Если интервал для установки новых ордеров еще не прошел:
            if(CheckAddingNew(tick.time) == true)
            {
              //  Установим реальные ордера на новых уровнях:
              OpenBuyLevels(live_option_level_value, live_option_level_value - prev_option_level_value);
            }
          }
          //  Позиции SELL:
          else if(live_option_level_sign == -1)
          {
            //  Если разрешена торговля:
            if(is_trade_allowed_Flag == true)
            {
              //  Если интервал для установки новых ордеров еще не прошел:
              if(CheckAddingNew(tick.time) == true)
              {
                //  Установим реальные ордера на новых уровнях:
                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;
        }
        //  Если значение УРОВНЯ эмуляции опционов УМЕНЬШИЛОСЬ, значит надо закрыть часть или все позиции на предыдущих уровнях:
        else if(live_option_level_value < prev_option_level_value)
        {
          //  Позиции BUY:
          if(live_option_level_sign == 1)
          {
            //  Если разрешена торговля:
            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:
          else if(live_option_level_sign == -1)
          {
            //  Если разрешена торговля:
            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);
              }
            }
          }
          //  Текущее значение (по модулю) уровня дельты при эмуляции опционов стало НУЛЕВЫМ (все позиции нужно закрыть):
          else  if(live_option_level_sign == 0)
          {
            //  Если разрешена торговля:
            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;      }
    }
  }
}

Monitoramos a alteração do nível de emulação das opções chamando o método UpdateOptionLevel. Se o nível mudou, esse método retorna true. Aqui comparamos os valores atual e anterior (no tick anterior) dos níveis de emulação das opções.

Quando é necessário rebalancear as posições, verificamos se o nível de emulação das opções aumentou ou diminuiu. Se aumentou, é necessário abrir posições adicionais. Se diminuiu, é necessário fechar parte das posições. Se o nível de emulação chegou a zero, fechamos todas as posições abertas. É assim que ocorre o rebalanceamento da posição agregada.

Observe que, como preço para calcular o delta atual da estrutura de opções, usamos a média entre Bid e Ask. Isso permite reduzir a dependência das variações do delta em relação às mudanças no spread. O texto completo do EA pode ser consultado nos arquivos que acompanham este artigo.

Na abertura e no fechamento de posições, são usadas ordens a mercado. Isso foi feito para simplificar a verificação do funcionamento do EA (há garantia de execução da ordem). Futuramente, recomenda-se (e isso será feito) passar a usar ordens limitadas para abrir posições. Isso permitirá reduzir os custos com comissões e melhorará os resultados de trading ao evitar o pagamento do spread na entrada nas posições.

Verificando em tempo real a emulação e o trading

Suponhamos que decidimos que, o preço do EURUSD tenderá a subir durante o dia. Definiremos o tipo da estrutura de opções OptionConstruction = ENUM_OPTION_CONSTRUCTION_RISING. Um exemplo de operação do EA que emula a estrutura de opções Base Active Rising - Long CALL é apresentado nas figuras abaixo: Fig. 1, a partir da abertura do dia; Fig. 2, um trecho ampliado das operações. Foram acionados os níveis de emulação de 1 a 9. No início da operação do EA, os níveis foram rebalanceados:

Fig. 1 Operação da estrutura de opções Base Active Rising - Long CALL — visão geral.

Fig. 2 Operação da estrutura de opções Base Active Rising - Long CALL — trecho ampliado.

Fig. 3 Estado atual das posições ao emular a estrutura de opções Base Active Rising - Long CALL

 

Fig. 4 Resultado do rebalanceamento ao emular a estrutura de opções Base Active Rising - Long CALL na forma de operações do histórico de trading

Agora suponhamos que, no dia seguinte, decidimos que o preço reverterá e seguirá para baixo. Definiremos o tipo da estrutura de opções OptionConstruction = ENUM_OPTION_CONSTRUCTION_FALLING. Desta vez, a sorte não esteve do nosso lado: no fim do dia, o preço reverteu contra nós e tivemos certo prejuízo. Na Fig. 5, vemos a execução da estrutura de opções definida. Foram abertos os níveis de emulação do 1º ao 5º. Nesse caso, o valor do prejuízo registrado devido ao rebalanceamento foi de -5.77 USD, veja a Fig. 6.

Fig. 5 Operação da estrutura de opções Base Active Rising - Long Put — visão geral

Fig. 6 Resultado do rebalanceamento ao emular a estrutura de opções Base Active Rising - Long Put na forma de operações do histórico de trading

O volume agregado máximo das posições pode chegar a 0.1 = 10 níveis * 0.01. Esse é o volume-alvo da estrutura de opções quando o multiplicador do lote mínimo é igual a um. Como visto na Fig. 4, o rebalanceamento da estrutura de opções resultou em um prejuízo realizado de -2.39 USD no primeiro caso e de -5.77 USD no segundo, veja a Fig. 6.. Isso é análogo ao prêmio pago pela compra da opção. Como definido no parâmetro de entrada ForceAutoExpirationTime = "23:50" do EA, a estrutura de opções expirou às 23:50, registrando um resultado positivo no primeiro caso. É claro que o resultado do trading depende da situação específica do mercado e das nossas ações.


Conclusão

Examinamos a implementação prática de um EA que emula uma estrutura de opções definida. Confirmamos que a prática corresponde aos fundamentos teóricos apresentados no primeiro artigo desta série. No próximo artigo, analisaremos a implementação de estratégias de opções com utilidade prática real. Elas são usadas por traders de opções que atuam no mercado.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/18363

Últimos Comentários | Ir para discussão (8)
prostotrader
prostotrader | 19 out. 2025 em 08:45

Boa tarde!

É claro que é interessante.

MAS!

Você:

--> Suponha que decidimos que, durante o dia, o preço do EURUSD se moverá principalmente para cima....

---> Agora, suponha que, no dia seguinte, decidimos que o preço se reverterá e cairá....

Novamente "jogando uma moeda", o que acabará e inevitavelmente levará à perda do depósito.

Você, Dmitry, fez um ótimo trabalho, mas isso não resultará em ganhos estáveis.

Adicionado

Fiz um experimento uma vez, há muito tempo.

Peguei uma seção de um ano para velas M1 e comprei primeiro na abertura da vela, e no fechamento - vendi e assim o ano inteiro.

Isso resultou em uma grande perda.

Depois, mudei a compra para a venda e a venda para a compra e, novamente, o ano inteiro. e....

Tive um grande prejuízo! :)

Adicionado

Negociação de um portfólio de cobertura de futuros de todas as ações da MOEX.

Riscos +85/-15%

Menos 15% porque eles podem anunciar dividendos inesperadamente

9 dias atrás

Hoje

Trabalhando duro para cortar -15%

Dmitriy Skub
Dmitriy Skub | 19 out. 2025 em 09:44

Não há estratégias de mercado que garantam ganhos estáveis. Incluindo a sua, especialmente nas condições atuais, quando não se sabe o que esperar do dia seguinte. É por isso que você pode ganhar algo apenas no dia, sem transferência, tudo IMHO.

Você tem como principal lucro o par de ações - futuros sobre ele, certo?

prostotrader
prostotrader | 19 out. 2025 em 09:50
Dmitriy Skub #:

Não há estratégias de mercado que garantam ganhos estáveis. Incluindo a sua, especialmente nas condições atuais, quando não se sabe o que esperar do dia seguinte. É por isso que você só pode ganhar algo no dia, sem transferência, tudo IMHO.

Você tem como principal lucro o par de ações - futuros sobre ele, certo?

Não, devido ao fato de que o Finam não dá desconto nas ações compradas, eu não uso essa estratégia "dourada" 100% lucrativa agora.

Agora, opero apenas futuros com carteira de hedge em absolutamente todas as ações da MOEX.

---> Dyck, não há estratégias de mercado que garantam ganhos consistentes.

Você simplesmente ainda não as conhece....

Ninguém, inclusive eu, vai lhe falar sobre elas.

Adicionado

Qualquer estratégia de hedge deve produzir lucros consistentes.

5 fatores são importantes

1. Riscos

2. Implementação adequada

3. Velocidade de execução das ordens de negociação

4. Ganância do operador (alguém ficará satisfeito com 50% ao ano, e alguém que nem mesmo 500% é suficiente - esse é o motivo pelo qual 99% dos operadores perdem....).

5. Negociação SOMENTE por meio de robôs (o fator humano deve ser completamente excluído)
Dmitriy Skub
Dmitriy Skub | 19 out. 2025 em 12:36

O que há para saber?

Você espera pela divergência máxima (no sentido estatístico) entre a ação e a bolsa, compra a ação nesse momento e vende a bolsa. Você espera o vencimento. Com um grande capital, essa é uma estratégia bastante funcional. Mas ela também tem seus riscos.

Anteriormente, você costumava comprar/vender divergência/convergência em um dia (dias), talvez fechando apenas uma perna.

Por que você não faz isso agora - aparentemente, não há liquidez suficiente.

Sergey Chalyshev
Sergey Chalyshev | 19 out. 2025 em 21:06

As opções e as estratégias de opções em si não geram nenhum lucro. Tudo é igual ao forex 50/50. A matemática é a mesma, distribuição normal de probabilidade.

As opções podem dar lucro (sem risco) somente quando usadas em combinação com futuros ou ações.

Do iniciante ao especialista: Criando um EA animado de notícias em MQL5 (III): Análise de indicadores Do iniciante ao especialista: Criando um EA animado de notícias em MQL5 (III): Análise de indicadores
Neste artigo, daremos continuidade à apresentação do EA "manchetes", apresentando uma faixa especial de "Análise de indicadores" (indicator insights): uma exibição compacta, no gráfico, dos principais sinais técnicos gerados por indicadores populares, como RSI, MACD, Stochastic e CCI. Essa abordagem elimina a necessidade de várias subjanelas de indicadores no terminal MetaTrader 5, mantendo sua área de trabalho limpa e eficiente. Usando a API MQL5 para acessar dados dos indicadores em segundo plano, podemos processar e visualizar informações de mercado em tempo real com lógica personalizada.
Do iniciante ao especialista: Criação de um EA de notícias animado em MQL5 (II) Do iniciante ao especialista: Criação de um EA de notícias animado em MQL5 (II)
Hoje damos mais um passo à frente, integrando uma API externa de notícias como fonte de manchetes para o nosso EA "Manchetes de notícias". Nesta etapa, vamos explorar diferentes fontes de notícias, tanto já existentes quanto novas, e aprender como usar suas APIs de forma eficiente. Também veremos métodos para fazer o parsing dos dados recebidos em um formato otimizado para exibição no nosso EA. Acompanhe a discussão enquanto analisamos as vantagens de usar manchetes de notícias e o calendário econômico diretamente no gráfico. Tudo isso em uma interface compacta e discreta.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Superando as limitações do aprendizado de máquina (Parte 1): carência de métricas compatíveis Superando as limitações do aprendizado de máquina (Parte 1): carência de métricas compatíveis
Neste artigo, mostramos que parte dos problemas que enfrentamos está enraizada em seguir cegamente as "melhores práticas". Ao apresentar ao leitor evidências simples, baseadas no mercado real, explicaremos por que devemos evitar esse comportamento e, em vez disso, adotar boas práticas baseadas em domínios específicos, caso nossa comunidade queira ter alguma chance de recuperar o potencial oculto da IA.