English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
Expert Advisor 처음부터 개발하기

Expert Advisor 처음부터 개발하기

MetaTrader 5트레이딩 | 6 5월 2022, 09:50
480 0
Daniel Jose
Daniel Jose

소개

금융 시장의 신규 사용자 수가 증가하고 있습니다. 그들 중 많은 사람들은 주문 시스템이 어떻게 작동하는지조차 모릅니다. 그러나 그안에서 실제로 무슨 일이 일어나고 있는지 알고 싶어하는 사용자들도 있습니다. 그들은 상황을 통제하기 위해 그 안의 모든 것이 어떻게 작동하는지 이해하려고 노력합니다.

물론 MetaTrader 5는 트레이딩과 관련한 높은 수준의 제어를 제공합니다. 그러나 수동으로 주문하는 것은 경험이 적은 사용자에게는 상당히 어렵고 위험할 수 있습니다. 만약 누군가가 선물을 거래하고자 하는데 주문을 전송할 시간이 없는데도 모든 필드를 시간에 쫒겨 정확하게 채워야 하는 경우가 있습니다. 이러한 거래는 악몽과 같은 결과를 초래할 수도 있습니다. 주문을 하는데 시간이 걸리고 따라서 무언가를 잘못 채워 넣게 되면 좋은 기회를 놓치거나 돈을 잃을 수도 있습니다.

EA(Expert Advisor)를 사용하여 작업을 더 쉽게 만들면 어떨까요? Expert Advisor의 경우에는 레버리지 또는 손실을 감당할 수 있는 정도와 얻고 싶은 수익(확실하지 않은 "포인트" 또는 "핍"이 아닌 금전적 측면에서)과 같은 세부 사항을 지정할 수 있습니다. 차트에서 마우스 포인터를 사용하여 시장에 진입할 위치를 표시하면 그곳이 매수 또는 매도 여부를 나타냅니다...


구상

무언가를 만들 때 가장 어려운 부분은 어떠한게 작동하는 것을 만들지를 결정하는 것입니다. 생성할 코드가 더 복잡할수록 런타임 오류의 가능성은 커지게 되므로 우리는 최소한의 필수적인 코드로 우리의 아이디어를 명확하게 공식화해야 합니다. 저는 이를 염두에 두고 코드를 아주 간단하게 만들려고 했고 MetaTrader 5에서 제공하는 기능을 최대한 활용했습니다. 플랫폼은 매우 안정적이고 지속적으로 테스트 중이므로 플랫폼 측면에서는 오류가 있을 수 없습니다.

코드는 OOP(객체 지향 프로그래밍)를 사용합니다. 이 접근 방식은 코드를 격리할 수 있도록 합니다. 그래서 추후 새로운 기능을 추가하고 개선하려는 경우에 유지 관리 및 개선을 용이하게 합니다.

이 기사에서 논의된 EA는 B3(브라질 거래소)에서의 거래, 특히 선물 거래(미니 인덱스 및 미니 달러)를 위해 설계되었지만 간단한 수정을 하면 모든 시장에서 사용할 수 있습니다. EA를 좀 더 쉽게 작동하도록 하기 위해 거래 자산을 나열하거나 확인하지 않도록 다음의 열거형을 사용합니다.

enum eTypeSymbolFast {WIN, WDO, OTHER};


만약 특수한 기능을 사용하는 다른 자산을 거래하려면 해당 자산을 열거형에 추가하십시오. 그러기 위해선 코드를 약간 변경해야 하지만 열거를 사용하면 오류 가능성도 줄어들기 때문에 훨씬 더 쉬울 것입니다. 코드의 흥미로운 부분은 AdjustPrice 함수입니다.

   double AdjustPrice(const double arg)
     {
      double v0, v1;
      if(m_Infos.TypeSymbol == OTHER)
         return arg;
      v0 = (m_Infos.TypeSymbol == WDO ? round(arg * 10.0) : round(arg));
      v1 = fmod(round(v0), 5.0);
      v0 -= ((v1 != 0) || (v1 != 5) ? v1 : 0);
      return (m_Infos.TypeSymbol == WDO ? v0 / 10.0 : v0);
     };

이 함수는 차트의 정확한 지점에 거래하고자 하는 포지션의 라인을 배치하기 위해 가격에 해당하는 값을 조정합니다. 차트에 단순히 라인을 놓을 수 없는 이유는 무엇일까요? 일부 자산에는 가격 사이에 특정 스텝(간격)이 있기 때문입니다. WDO(미니 달러)의 경우 이 스텝은 0.5포인트에 불과합니다. WIN(미니 인덱스)의 경우 이 스텝은 5포인트이고 주식의 경우 0.01포인트입니다. 즉 포인트 값은 자산마다 다릅니다. 이렇게 하면 가격이 정확한 틱 값으로 조정되어 주문에 적절한 값이 사용됩니다. 그렇지 않으면 잘못된 주문이 서버에서 거부될 수 있습니다.

이 함수가 없으면 주문에 사용할 올바른 값을 알기 어려울 수 있습니다. 그런 경우 서버는 잘못된 주문이라고 경고를 보내거나 주문이 실행되지 않게 될수도 있습니다. 이제 Expert Advisor의 핵심인 CreateOrderPendent 함수에 대해 알아보겠습니다. 함수는 다음과 같습니다:

   ulong CreateOrderPendent(const bool IsBuy, const double Volume, const double Price, const double Take, const double Stop, const bool DayTrade = true)
     {
      double last = SymbolInfoDouble(m_szSymbol, SYMBOL_LAST);
      ZeroMemory(TradeRequest);
      ZeroMemory(TradeResult);
      TradeRequest.action        = TRADE_ACTION_PENDING;
      TradeRequest.symbol        = m_szSymbol;
      TradeRequest.volume        = Volume;
      TradeRequest.type          = (IsBuy ? (last >= Price ? ORDER_TYPE_BUY_LIMIT : ORDER_TYPE_BUY_STOP) : (last < Price ? ORDER_TYPE_SELL_LIMIT : ORDER_TYPE_SELL_STOP));
      TradeRequest.price         = NormalizeDouble(Price, m_Infos.nDigits);
      TradeRequest.sl            = NormalizeDouble(Stop, m_Infos.nDigits);
      TradeRequest.tp            = NormalizeDouble(Take, m_Infos.nDigits);
      TradeRequest.type_time     = (DayTrade ? ORDER_TIME_DAY : ORDER_TIME_GTC);
      TradeRequest.stoplimit     = 0;
      TradeRequest.expiration    = 0;
      TradeRequest.type_filling  = ORDER_FILLING_RETURN;
      TradeRequest.deviation     = 1000;
      TradeRequest.comment       = "Order Generated by Experts Advisor.";
      if(!OrderSend(TradeRequest, TradeResult))
        {
         MessageBox(StringFormat("Error Number: %d", TradeResult.retcode), "Nano EA");
         return 0;
        };
      return TradeResult.order;
     };

이 함수는 매우 간단하며 안전하게 설계되었습니다. 여기서 우리는 OCO 주문(하나의 주문이 다른 하나를 취소)을 생성하고 이 주문은 거래 서버로 전송됩니다. LIMIT 또는STOP 주문을 사용하고 있다는 것을 기억하세요. 왜냐하면 이러한 종류의 주문은 간단하기도 하지만 급격한 가격 변동에도 실행이 보장되기 때문입니다.

사용할 주문 유형은 실행 가격과 거래 상품의 현재 가격 그리고 매수 또는 매도 중 어느 포지션으로 진입하는지 등의 여부에 따라 달라집니다. 이는 다음의 라인에서 구현됩니다:

TradeRequest.type = (IsBuy ? (last >= Price ? ORDER_TYPE_BUY_LIMIT : ORDER_TYPE_BUY_STOP) : (last < Price ? ORDER_TYPE_SELL_LIMIT : ORDER_TYPE_SELL_STOP));

다음 라인에서 거래 상품을 지정하여 교차 주문을 생성할 수도 있습니다.

TradeRequest.symbol = m_szSymbol;

그러나 그렇게 할 경우 "잘못된" 차트가 있을 경우 교차 주문 시스템을 통해 미결 또는 보류 중인 주문을 처리하기 위해 일부의 코드를 추가해야 합니다. 예를 들어 보겠습니다. 여러분이 전체 지수 차트(IND)에 있으면서 미니 지수(WIN)를 거래할 수는 있지만 MetaTrader 5는 여러분이 IND 차트에 있을 때 미결 또는 보류 중인 WIN 주문을 표시하지 않습니다. 따라서 주문을 볼 수 있도록 코드를 추가해야 합니다. 이것은 포지션 값을 읽고 차트에 선으로 표시하여 할 수 있습니다. 이는 심볼을 거래하고 거래 내역을 추적할 때 매우 유용합니다. 예를 들어 CROSS ORDER를 사용하면 WIN (Mini index)를 사용하여WIN$ 차트(Mini Index 히스토리 차트)를 거래할 수 있습니다.

다음으로 다음의 코드 라인에 주의하십시오.

      TradeRequest.price         = NormalizeDouble(Price, m_Infos.nDigits);
      TradeRequest.sl            = NormalizeDouble(Stop, m_Infos.nDigits);
      TradeRequest.tp            = NormalizeDouble(Take, m_Infos.nDigits);

이 3개의 라인은 OCO 주문의 스탑 레벨과 포지션 진입 가격을 생성합니다. 만약 몇 초만 보유하는 단기 주문을 거래하는 경우 OCO 주문을 사용하지 않고 거래 하는 것은 바람직하지 않습니다. 변동성으로 인해 명확한 방향 없이 가격이 한 지점에서 다른 지점으로 이동할 수 있기 때문입니다. OCO를 사용하면 거래 서버 자체에서 포지션을 처리합니다. OCO 주문은 다음과 같이 나타납니다.

편집 창에서 동일한 주문은 다음과 같이 보입니다:

모든 필수기입 필드를 채우면 서버에서 주문을 관리합니다. 최대 이익 또는 최대 손실의 어느 쪽이든 도달하자 마자 시스템이 주문을 청산합니다. 그러나 만약 최대 이익 또는 최대 손실을 지정하지 않으면 다른 이벤트가 발생할 때까지 주문이 미결 상태로 유지될 수 있습니다. 주문 유형이 데이 트레이드로 설정된 경우 시스템은 거래일이 끝나면 청산합니다. 그렇지 않으면 포지션을 수동으로 청산하거나 포지션을 유지하기 위한 자금이 더 이상 없을 때까지 포지션이 보유 상태로 유지됩니다.

일부 Expert Advisor 시스템은 포지션을 청산하기 위해 또다른 주문을 사용합니다: 포지션에 진입하면 동일한 볼륨으로 지정된 지점에서 포지션을 청산하기 위한 반대 주문이 전송됩니다. 그러나 어떤 이유로 인해 자산이 세션 중에 경매에 들어가면 보류 중인 주문이 취소될 수 있고 교체되어야 하기 때문에 일부 시나리오에서는 작동하지 않을 수 있습니다. 이것은 EA가 작업을 수행하는 것을 복잡하게 만듭니다. 어떤 주문이 활성화 되었고 어떤 것이 비활성화 되었는지를 확인하는 작업을 추가해야 하기 때문입니다. 만약 무언가가 잘못되면 EA가 아무 기준 없이 주문을 차례로 보내게 됩니다.

   void Initilize(int nContracts, int FinanceTake, int FinanceStop, color cp, color ct, color cs, bool b1)
     {
      string sz0 = StringSubstr(m_szSymbol = _Symbol, 0, 3);
      double v1 = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
      m_Infos.Id = ChartID();
      m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));
      m_Infos.nDigits = (int) SymbolInfoInteger(m_szSymbol, SYMBOL_DIGITS);
      m_Infos.Volume = nContracts * (m_VolMinimal = SymbolInfoDouble(m_szSymbol, SYMBOL_VOLUME_MIN));
      m_Infos.TakeProfit = AdjustPrice(FinanceTake * v1 / m_Infos.Volume);
      m_Infos.StopLoss = AdjustPrice(FinanceStop * v1 / m_Infos.Volume);
      m_Infos.IsDayTrade = b1;
      CreateHLine(m_Infos.szHLinePrice, m_Infos.cPrice = cp);
      CreateHLine(m_Infos.szHLineTake, m_Infos.cTake = ct);
      CreateHLine(m_Infos.szHLineStop, m_Infos.cStop = cs);
      ChartSetInteger(m_Infos.Id, CHART_COLOR_VOLUME, m_Infos.cPrice);
      ChartSetInteger(m_Infos.Id, CHART_COLOR_STOP_LEVEL, m_Infos.cStop);
     };

위의 루틴은 사용자가 지시한 대로 EA 데이터가 시작되도록 합니다. - 즉 OCO 주문을 생성합니다. 이 루틴에서 우리는 다음의 내용만 변경하면 됩니다.

m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));

여기에 특정 항목이 필요한 경우 현재 항목에 추가하여 거래 심볼의 유형을 추가합니다.

      m_Infos.Volume = nContracts * (m_VolMinimal = SymbolInfoDouble(m_szSymbol, SYMBOL_VOLUME_MIN));
      m_Infos.TakeProfit = AdjustPrice(FinanceTake * v1 / m_Infos.Volume);
      m_Infos.StopLoss = AdjustPrice(FinanceStop * v1 / m_Infos.Volume);

위의 세 줄은 주문이 올바르게 생성되도록 하기 위해 필요한 조정을 수행합니다. nContracts는 레버리지 요소입니다. 1, 2, 3 등과 같은 값을 사용하십시오. 이를 사용하면 거래하고자 하는 심볼의 최소 볼륨을 알 필요가 없습니다. 이 최소 거래량의 레버리지 요소를 표시하기만 하면 됩니다. 예를 들어 필요한 최소 거래량이 5계약이고 레버리지 계수를 3으로 지정하면 시스템은 15계약의 주문을 전송합니다. 다른 두 줄은 사용자가 지정한 매개변수를 기반으로 하는 Take Profit 그리고Stop Loss에 따라 설정됩니다. 레벨은 주문량에 따라 조정됩니다. 주문이 증가하면 레벨이 감소하고 그 반대의 경우도 마찬가지입니다. 이 코드를 사용하면 포지션을 생성하기 위해 계산을 할 필요가 없습니다. EA는 모든 것을 자체적으로 계산합니다. 어떤 금융 상품을 어떤 레버리지 요소로 거래할 것인지 얼마나 많은 돈을 벌고 싶고 잃을 준비가 되었는지 EA가 적절한 주문을 할 것입니다.

   inline void MoveTo(int X, int Y, uint Key)
     {
      int w = 0;
      datetime dt;
      bool bEClick, bKeyBuy, bKeySell;
      double take = 0, stop = 0, price;
      bEClick  = (Key & 0x01) == 0x01;    //Left mouse button click
      bKeyBuy  = (Key & 0x04) == 0x04;    //Pressed SHIFT
      bKeySell = (Key & 0x08) == 0x08;    //Pressed CTRL
      ChartXYToTimePrice(m_Infos.Id, X, Y, w, dt, price);
      ObjectMove(m_Infos.Id, m_Infos.szHLinePrice, 0, 0, price = (bKeyBuy != bKeySell ? AdjustPrice(price) : 0));
      ObjectMove(m_Infos.Id, m_Infos.szHLineTake, 0, 0, take = price + (m_Infos.TakeProfit * (bKeyBuy ? 1 : -1)));
      ObjectMove(m_Infos.Id, m_Infos.szHLineStop, 0, 0, stop = price + (m_Infos.StopLoss * (bKeyBuy ? -1 : 1)));
      if((bEClick) && (bKeyBuy != bKeySell))
         CreateOrderPendent(bKeyBuy, m_Infos.Volume, price, take, stop, m_Infos.IsDayTrade);
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLinePrice, OBJPROP_COLOR, (bKeyBuy != bKeySell ? m_Infos.cPrice : clrNONE));
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLineTake, OBJPROP_COLOR, (take > 0 ? m_Infos.cTake : clrNONE));
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLineStop, OBJPROP_COLOR, (stop > 0 ? m_Infos.cStop : clrNONE));
     };

위의 코드는 생성될 주문을 나타냅니다. 이 코드는 마우스의 움직임을 사용하여 주문이 전송될 위치를 표시합니다. 이때 EA에 매수(SHIFT를 누르고 있음) 또는 매도(CTRL을 누르고 있음) 여부를 알리고 싶은 경우가 있습니다. 이때 마우스의 왼쪽 버튼을 클릭하면 해당 지점에 대기 주문이 생성됩니다.

손익분기점과 같이 더 많은 데이터를 표시해야 하는 경우에는 관련 객체를 코드에 추가하면 됩니다.

이제 OCO 주문을 생성할 수 있는 EA가 완성되었습니다. 하지만 아직 모든 것이 완벽하지는 않습니다 ...


OCO 주문의 문제

OCO 주문에는 한 가지 문제가 있습니다. 물론 MetaTrader 5 시스템이나 거래 서버가 잘못된 것은 아닙니다. OCO주문은 시장에 지속적으로 존재하는 변동성 자체와 연결됩니다. 이론적으로 가격은 롤백 없이 선형적으로 움직여야 하지만 때로는 변동성이 높아서 캔들의 안에서 을 형성합니다. 이러한 갭이 손절매 또는 이익실현 주문 가격이 있는 지점에서 발생하면 이러한 지점은 트리거로 동작하지 않게 되므로 포지션이 청산되지 않습니다. 또한 사용자가 이 포인트를 변경할때 가격이 손절매와 이익실현으로 형성된 범위를 넘어설 수 있습니다. 이 경우에도 주문은 실행되지 않습니다. 이는 예측이 불가능한 매우 위험한 상황입니다. 프로그래머는 가능한 손실을 최소화하기 위한 메커니즘을 제공해야 합니다.

가격을 새로 고치고 범위 내에서 유지하기 위해 두 개의 서브루틴을 사용합니다. 첫 번째는 다음과 같습니다:

   void UpdatePosition(void)
     {
      for(int i0 = PositionsTotal() - 1; i0 >= 0; i0--)
         if(PositionGetSymbol(i0) == m_szSymbol)
           {
            m_Take      = PositionGetDouble(POSITION_TP);
            m_Stop      = PositionGetDouble(POSITION_SL);
            m_IsBuy     = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY;
            m_Volume    = PositionGetDouble(POSITION_VOLUME);
            m_Ticket    = PositionGetInteger(POSITION_TICKET);
           }
     };

이는 OnTrade에서 호출됩니다 - 모든 포지션 수정에 대해 MetaTrader 5에 의해 호출되는 함수. 다음에 사용될 서브루틴은 OnTick에 의해 호출됩니다. 이는 가격이 범위 내에 있거나 OCO 주문의 한도 내에 있는지 확인합니다. 다음과 같습니다:

   inline bool CheckPosition(const double price = 0, const int factor = 0)
     {
      double last;
      if(m_Ticket == 0)
         return false;
      last = SymbolInfoDouble(m_szSymbol, SYMBOL_LAST);
      if(m_IsBuy)
        {
         if((last > m_Take) || (last < m_Stop))
            return ClosePosition();
         if((price > 0) && (price >= last))
            return ClosePosition(factor);
        }
      else
        {
         if((last < m_Take) || (last > m_Stop))
            return ClosePosition();
         if((price > 0) && (price <= last))
            return ClosePosition(factor);
        }
      return false;
     };

이 코드 조각은 모든 틱 변경 시마다 실행되고 매우 중요하므로 계산과 테스트가 가능한 한 효율적으로 수행될 수 있도록 최대한 단순해야 합니다. 범위 내부에서 가격을 유지하면서 원하는 경우에는 제거도 할 수 있는 흥미로운 내용도 체크합니다. 이와 관련한 추가적인 테스트는 다음 섹션에서 설명하겠습니다. 이 서브루틴의 내부에는 다음과 같은 함수 호출이 있습니다:

   bool ClosePosition(const int arg = 0)
     {
      double v1 = arg * m_VolMinimal;
      if(!PositionSelectByTicket(m_Ticket))
         return false;
      ZeroMemory(TradeRequest);
      ZeroMemory(TradeResult);
      TradeRequest.action     = TRADE_ACTION_DEAL;
      TradeRequest.type       = (m_IsBuy ? ORDER_TYPE_SELL : ORDER_TYPE_BUY);
      TradeRequest.price      = SymbolInfoDouble(m_szSymbol, (m_IsBuy ? SYMBOL_BID : SYMBOL_ASK));
      TradeRequest.position   = m_Ticket;
      TradeRequest.symbol     = m_szSymbol;
      TradeRequest.volume     = ((v1 == 0) || (v1 > m_Volume) ? m_Volume : v1);
      TradeRequest.deviation  = 1000;
      if(!OrderSend(TradeRequest, TradeResult))
        {
         MessageBox(StringFormat("Error Number: %d", TradeResult.retcode), "Nano EA");
         return false;
        }
      else
         m_Ticket = 0;
      return true;
     };

이 함수는 지정된 볼륨을 청산하고 보호장치의 역할을 합니다. 그러나 MetaTrader 5 클라이언트 터미널에서 함수가 실행되기 때문에 언제나 서버에 연결되어야 한다는 것을 잊지 마십시오. 서버와의 연결이 되지 않으면 이 기능은 완전히 쓸모가 없어지게 됩니다.

이 마지막 두 코드를 보면 특정 지점에서 원하는 볼륨을 없앨 수 있음을 알 수 있습니다. 그렇게 함으로써 우리는 부분적인 청산을 하거나 위험을 줄입니다. 이 기능을 어떻게 사용하는지 알아봅시다.


부분 주문 작업


부분 주문은 많은 거래자가 좋아하고 실제로 많이 사용하는 것입니다. Expert Advisor는 부분 청산 작업을 허용하지만 부분 주문은 별도의 주제여야 하므로 여기에서는 부분 청산의 코드를 구현하는 방법은 시현하지 않겠습니다. 그러나 부분 청산 작업을 구현하려면 간단히 CheckPosition 루틴을 실행하고 주문이 실행될 가격과 수량을 지정하면 나머지는 EA가 처리합니다.

부분 주문은 매우 개별적이고 모든 사람을 만족시킬 수 있는 일반 솔루션을 만들기가 어렵기 때문에 특별한 경우라고 할수 있습니다. 동적 배열의 사용은 스윙할 수 있으므로 여기에서 적합하지 않습니다 - EA가 동작하도록 놔두는 경우에만 당일 거래에 사용할 수 있습니다. 어떤 이유로든 EA를 비활성 해야 하는 경우에는 배열 솔루션이 작동하지 않습니다. 그러므로 데이터 형식이 데이터로 수행할 작업에 따라 달라지는 일부 저장 매체를 사용해야 합니다.

어쨌든 위험이 크므로 포지션 진입 오더를 이용한 부분 청산은 최대한 피해야 합니다. 여러분이 3배 레버리지의 매수 포지션을 가지고 있고 1배 레버리지 포지션을 유지하면서 2배로 수익을 내고 싶다고 가정해 보겠습니다. 이것은 2배 레버리지를 매도하여 할 수 있습니다. 그러나 EA가 시장가 매도 주문을 보내는 경우 변동성으로 인해 매도 주문이 실제로 실행되기 전에 가격이 올라가 이익실현 지점 도달할 수 있습니다. 이 경우 EA는 불리한 방향으로 새로운 매도 포지션을 열게 됩니다. 다른 방법으로는 2배 레버리지로 포지션을 축소하기 위해 매도 리밋 또는매도 스탑 주문을 전송할 수도 있습니다. 이것은 적절한 해결책으로 보일 수도 있습니다. 그러나 가격이 부분적으로 포인트에 도달하기 전에 다른 주문이 전송되면 어떻게 될까요 - 매우 안좋은 상황이 예상됩니다: 보유 포지션이 청산되고 조금 후에 주문이 다시 열리고 손실이 증가합니다. 변동성이 강해질수록 위에 언급한 같은 상황이 심해질 것입니다.

따라서 프로그래머로서 제가 생각하는 부분 주문을 하는 가장 좋은 방법은 시장 가격으로 주문을 내보내는 것입니다. 그러나 보유량을 초과하지 않도록 각별히 주의해야 합니다. 이 EA에서는 저는 정확히 이런 식으로 했습니다. 원한다면 여러분은 또 다른 부분 청산 방법을 구현할 수 있습니다.


결론

거래를 위한 Expert Advisor를 만드는 것은 일부 사람들이 생각하는 것만큼 쉬운 일이 아닙니다. 우리가 프로그래밍할 때 종종 직면하는 다른 문제들에 비해서는 매우 간단하지만 Expert Advisor는 금전적 위험과 연결되어 있습니다. 안정적이고 신뢰할 수 있는 시스템을 구축하는 것은 어려운 작업입니다. 이 기사에서 저는 MetaTrader 5를 사용하기 시작한 사람들과 EA를 프로그래밍하기 위해 필요한 지식이 없는 사람들을 위한 EA 제작 방법을 보여드렸습니다. 이 EA는 주문을 하지 않고 보다 안정적인 방식으로 주문을 하는 데 도움을 주기 때문에 좋은 시작점입니다. 주문이 전송되면 EA는 다른 할 일이 없으며 위에서 언급한 코드 조각을 제외하고는 MetaTrader 5가 작동을 맡습니다.

이 기사에서 제공한 Expert Advisor는 매개변수 세트로 작업하기 위해 다양한 방식으로 개선될 수 있지만 이를 위해서는 EA가 MetaTrader 5로부터 좀 더 독립적으로 작동하도록 하는 더 많은 코드가 필요합니다.

이 EA의 장점은 코드에는 작성하지 않은 작업 내용을 MetaTrader 5를 사용해서 수행한다는 것이며 따라서 매우 안정적이고 신뢰할 수 있다는 것입니다.





MetaQuotes 소프트웨어 사를 통해 포르투갈어가 번역됨
원본 기고글: https://www.mql5.com/pt/articles/10085

파일 첨부됨 |
EA_Nano_rvl_1.1.mq5 (23.44 KB)
Fix PriceAction 손절매 혹은 Fixed RSI(스마트 스탑로스) Fix PriceAction 손절매 혹은 Fixed RSI(스마트 스탑로스)
손절매는 거래에서 자금 관리와 관련된 중요한 도구입니다. 손절매와 이익실현과 랏 크기를 효과적으로 사용하면 트레이더는 더 일관되면서도 전반적으로도 더 많은 수익을 얻을 수 있습니다. 손절매는 훌륭한 도구이지만 사용할 때 직면하게 되는 문제들이 있습니다. 가장 중요한 것은 손절매 사냥입니다. 이 기사에서는 거래에서 손절매 사냥을 줄이는 방법과 전통적인 손절매 사용법을 비교하고 이를 통해 수익성을 결정하는 방법을 살펴봅니다.
알고리즘에 기반한 트레이딩 시스템을 설계하는 이유와 방법 알고리즘에 기반한 트레이딩 시스템을 설계하는 이유와 방법
이 글에서는 MQL5와 관련한 몇가지 기본적인 사항에 대해 살펴본 후 간단한 알고리즘 거래 시스템의 설계를 통해 초보자가 알고리즘 거래 시스템(Expert Advisor)을 설계할 때 필요한 MQL의 기본적인 것들을 보여줄 것입니다.
다양한 이동 평균 시스템을 설계하는 방법 다양한 이동 평균 시스템을 설계하는 방법
어떠한 전략이든 생성된 신호를 필터링하는 데 사용할 수 있는 많은 전략이 있습니다. 이 글의 주제인 이동 평균을 사용하는 경우도 마찬가지입니다. 따라서 이 글의 목적은 이동 평균 전략과 알고리즘 거래 시스템을 설계하는 방법을 공유하는 것입니다.
MQL 언어를 사용하여 아무것도 없는 상태에서 심층 신경망(Deep Neural Network) 프로그래밍 하기 MQL 언어를 사용하여 아무것도 없는 상태에서 심층 신경망(Deep Neural Network) 프로그래밍 하기
이 기사는 MQL4/5 언어를 사용하여 심층 신경망을 만드는 방법을 열려주는 것을 목표로 합니다.