공부방 ›

[강좌] [EA 만들기 4] 첫 EA 코드: 이동평균 크로스 (복사해서 바로 쓰기)

大현자 마스터운영진2026. 11. 01. 03:21조회 274추천 21댓글 0

3편에서 정한 규칙을 그대로 코드로 옮겨볼게요. MetaEditor에서 2편에 만든 `MyFirstEA` 내용을 전부 지우고 아래 코드를 붙여넣은 뒤 F7(컴파일)을 누르세요.

#include <Trade/Trade.mqh>          // 주문을 쉽게 내주는 도구 불러오기

input int    FastMA  = 20;          // 빠른 이동평균 기간
input int    SlowMA  = 50;          // 느린 이동평균 기간
input double Lots    = 0.01;        // 주문 수량
input int    StopPts = 3000;        // 손절 (포인트, 금 2자리 기준 3000 = 30달러)
input int    TakePts = 6000;        // 익절 (포인트)
input long   Magic   = 20261103;    // 이 EA 주문에 붙는 이름표

CTrade   trade;
int      hFast, hSlow;              // 이동평균 계산기 번호
datetime lastBar = 0;               // 마지막으로 확인한 봉 시간

int OnInit()
{
   hFast = iMA(_Symbol, _Period, FastMA, 0, MODE_EMA, PRICE_CLOSE);
   hSlow = iMA(_Symbol, _Period, SlowMA, 0, MODE_EMA, PRICE_CLOSE);
   if(hFast == INVALID_HANDLE || hSlow == INVALID_HANDLE) return INIT_FAILED;
   trade.SetExpertMagicNumber(Magic);
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   IndicatorRelease(hFast);
   IndicatorRelease(hSlow);
}

// 이 EA가 연 포지션이 지금 있는지
bool HasPosition()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong t = PositionGetTicket(i);
      if(PositionSelectByTicket(t)
         && PositionGetString(POSITION_SYMBOL) == _Symbol
         && PositionGetInteger(POSITION_MAGIC) == Magic) return true;
   }
   return false;
}

void OnTick()
{
   // 1) 새 봉이 생겼을 때만 판단
   datetime bar = iTime(_Symbol, _Period, 0);
   if(bar == lastBar) return;
   lastBar = bar;

   // 2) 방금 끝난 봉(1)과 그 전 봉(2)의 이동평균 값 가져오기
   double f[], s[];
   ArraySetAsSeries(f, true);
   ArraySetAsSeries(s, true);
   if(CopyBuffer(hFast, 0, 1, 2, f) < 2 || CopyBuffer(hSlow, 0, 1, 2, s) < 2) return;

   bool goldenCross = f[1] <= s[1] && f[0] > s[0];   // 아래 → 위로 교차
   bool deadCross   = f[1] >= s[1] && f[0] < s[0];   // 위 → 아래로 교차

   // 3) 이미 포지션이 있으면 쉬기 (한 번에 1개)
   if(HasPosition()) return;

   // 4) 주문
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   if(goldenCross)
      trade.Buy(Lots, _Symbol, ask,
                NormalizeDouble(ask - StopPts * _Point, _Digits),
                NormalizeDouble(ask + TakePts * _Point, _Digits), "MA cross");
   else if(deadCross)
      trade.Sell(Lots, _Symbol, bid,
                 NormalizeDouble(bid + StopPts * _Point, _Digits),
                 NormalizeDouble(bid - TakePts * _Point, _Digits), "MA cross");
}

줄별로 무슨 뜻인지

  • input: EA를 차트에 붙일 때 바꿀 수 있는 설정값이에요. 코드를 안 고치고 숫자만 바꿔 실험할 수 있어요.
  • iMA: 이동평균 계산기를 만들어요. OnInit에서 한 번만 만들고 계속 써요.
  • CopyBuffer(…, 1, 2, …): 1번 봉(방금 끝난 봉)부터 2개 값을 가져와요. `f[0]`이 방금 끝난 봉, `f[1]`이 그 전 봉이에요.
  • Magic: 이 EA가 낸 주문에 붙는 이름표예요. 다른 EA나 손으로 낸 주문과 섞이지 않게 해줘요.
  • _Point: 그 종목의 가장 작은 가격 단위예요. 금(소수 2자리)은 0.01이라 3000포인트 = 30달러예요.

확인해 보기

  1. F7 → `0 errors` 확인
  2. MT5에서 XAUUSD 15분 차트에 붙이기 (데모 계좌!)
  3. 아래 도구상자 → 전문가 탭에 에러가 없는지 보기
  4. 교차가 생기면 주문이 들어가요. 15분봉이라 몇 시간 걸릴 수 있어요.
바로 결과를 보고 싶으면 다음 글들의 전략 테스터를 쓰면 몇 년치를 몇 초 만에 돌려볼 수 있어요. 그 전에 5편에서 수량을 제대로 정하는 법부터 볼게요.

댓글 0

목록
Vantage 앱 광고광고
현자 탄생기념 부스터 이벤트