MT5 데모 계좌에서 첫 EA를 실행해 봅니다
이번 포스트의 핵심 내용 3줄요약
- MT5 데모 계좌에서 첫 EA를 실행하는 목적은 수익 전략을 완성하는 것이 아니라, 소스부터 로그까지 이어지는 실행 흐름을 검증하는 것입니다.
- 예시 코드는 전부 이해하지 않아도 됩니다. 전체 복사, 붙여넣기, F7 컴파일,
0 errors확인만 따라 하면 됩니다. - 데모 차트에서 Algo Trading 권한, Inputs 값, Experts와 Journal 로그를 확인하고 실행 조건을 기록하는 습관을 먼저 만들면 됩니다.
Expert Advisor, 줄여서 EA를 처음 실행할 때는 특정 브로커, 상품, 전략 유형이 필요하지 않습니다. 먼저 데모 계좌에서 EA가 어디에 저장되고, 어떻게 컴파일되며, 어떤 권한과 로그를 통해 동작을 확인하는지 알아야 합니다.
이 글은 MetaTrader 5에서 교육용 EA를 실행해 보려는 사람을 위한 첫 실습입니다. 성공 기준은 수익이 아니라 소스 파일 → 컴파일 → Navigator → 데모 차트 → 권한 → Experts·Journal 로그가 한 번 끊기지 않고 재현되는 것입니다. 브로커를 이용한다면 계좌·서버·심볼·터미널 빌드·계좌 모드를 함께 기록해 두면 같은 결과를 다시 확인하기 쉽습니다.
이 글은 특정 자동매매 전략을 판매하거나 성과를 약속하기 위한 글이 아닙니다. 최근에는 EA 파일, 자동매매 강의, 알고리즘 트레이딩 전략을 유료로 판매하는 곳이 많습니다. 유료 자료를 보더라도 최소한 사용자가 직접 “EA가 어디에 저장되고, 어떻게 컴파일되고, 어떤 권한으로 주문을 보내는지”는 이해해야 합니다.
처음 사용하는 사람도 따라올 수 있도록 화면 이름부터 차례로 정리하겠습니다. 이번 글의 목표는 돈을 버는 전략을 완성하는 것이 아니라 MT5에서 첫 EA가 실행되는 구조를 직접 확인하는 것입니다.
EA, MQL5, 코드가 아직 낯설다면 이번에는 순서대로 실행해 보는 데만 집중해도 됩니다. 전략 설계와 코드 해석은 다음 단계에서 다룹니다.
이 실습에서 검증하는 것과 검증하지 않는 것
| 구분 | 이 글에서 확인하는 것 | 이 글만으로 확인할 수 없는 것 |
|---|---|---|
| 기술 동작 | 코드가 컴파일되는지, EA가 차트에 붙는지, 로그가 남는지 | 전략의 수익성이나 장기 안정성 |
| 주문 조건 | 데모에서 권한·입력값·심볼 규칙 오류를 읽는 방법 | 실계좌 체결 품질, 슬리피지, 비용 |
| 기록 | MT5 빌드, 데모 서버·계좌 모드, 심볼·시간봉, EA 버전과 Inputs | 다른 환경에서도 같은 성과가 난다는 보장 |
| 개인정보 | 비밀번호·계좌번호·신분증이 보이지 않는 화면으로 실습 | 브로커의 개인정보 처리 방식 전체 |
스크린샷이나 로그를 공유할 때는 계좌번호, 서버 로그인 정보, 주문 식별자, 개인정보가 노출되지 않는지 먼저 확인합니다. 이 글의 예제는 데모 환경의 기능 확인용이며, 실거래 전용 코드나 운용 절차가 아닙니다.
이번 글에서 배울 것
| 단계 | 무엇을 배우는가 | 왜 중요한가 |
|---|---|---|
| 1 | 데모 계좌의 역할 | 실계좌 전에 조작 실수를 줄임 |
| 2 | MT5 화면 이름 | Market Watch, Navigator, Toolbox를 구분 |
| 3 | MetaEditor에서 EA 파일 만들기 | 자동매매가 어떤 파일로 동작하는지 이해 |
| 4 | 예시 EA 코드 붙여넣기 | 첫 컴파일 경험 만들기 |
| 5 | 0 errors, 0 warnings 확인 | 실행 가능한 .ex5 파일 생성 |
| 6 | 차트에 EA 붙이기 | 데모 차트에서 자동매매 권한과 Inputs 확인 |
| 7 | Journal 로그 확인 | 주문 실패와 권한 문제를 읽는 습관 |
이번 글 다음에는 MT5 Strategy Tester 백테스트 가이드로 이어집니다. 자동매매에서 더 중요한 단계는 “EA를 켜는 것”보다 “과거 데이터와 조건을 명시해 검증하는 것”입니다. 다만 백테스트를 하려면 먼저 테스트할 EA 파일이 있어야 하므로, 이번 글에서 그 준비를 끝냅니다.

데모 계좌는 무엇이고 무엇이 아닌가
데모 계좌는 실제 돈이 아니라 가상 잔고로 주문을 넣어 보는 계좌입니다. 초보자는 데모 계좌를 “실거래 전 클릭 연습” 정도로 생각하기 쉽지만, 시스템 트레이딩에서는 훨씬 더 중요합니다.
| 구분 | 데모 계좌에서 확인할 것 | 데모 계좌만으로 판단하면 안 되는 것 |
|---|---|---|
| 주문 실행 | EA가 주문을 보내는지, 주문 방향이 맞는지 | 실계좌 체결 품질이 완전히 같다는 판단 |
| 포지션 관리 | 같은 심볼에 포지션이 중복되는지 | 큰 금액에서도 동일하게 안정적이라는 판단 |
| 로그 | 에러 메시지, 거래 거부, 자동매매 권한 문제 | 장기간 운영 안정성 전체 |
| 손절과 익절 | 손절·익절 주문이 들어가는지 | 모든 시장 상황에서 원하는 가격에 체결된다는 판단 |
| 조작 연습 | 버튼 위치, 차트 조작, EA 삭제 방법 | 실제 돈을 넣었을 때의 심리 반응 |
데모 계좌는 반드시 필요하지만 충분하지는 않습니다. CFD, Forex, 지수, 원자재 같은 상품은 스프레드, 슬리피지, 거래 시간, 스왑, 레버리지, 랏 설정에 따라 실계좌 결과가 달라질 수 있습니다. 이 글의 교육용 EA로 진행할 범위는 EA 실행 연습 → Strategy Tester 백테스트 → 장기 데모 검증까지입니다. 이 예제 EA를 실계좌에서 사용하면 안 됩니다. 실계좌 전환은 포지션 소유권, 주문 수량, 손실 한도, 체결 결과 복구까지 별도로 구현하고 검토한 코드에서만 판단해야 합니다.
MT5 화면에서 알아야 할 위치
먼저 MT5 화면 이름부터 익히는 편이 좋습니다. 메뉴 이름을 모르면 설명을 봐도 따라가기 어렵습니다.
| 화면 영역 | 위치 | 역할 |
|---|---|---|
| Market Watch | 보통 왼쪽 위 | 거래 가능한 심볼과 현재 시세 확인 |
| Navigator | 보통 왼쪽 아래 | 계좌, 지표, Expert Advisors 목록 확인 |
| Chart | 가운데 큰 영역 | 캔들 차트와 EA 부착 위치 |
| Toolbox | 보통 아래쪽 | Trade, History, Experts, Journal 로그 확인 |
| Algo Trading 버튼 | 상단 도구막대 | 플랫폼 전체 자동매매 허용 또는 차단 |
| MetaEditor | F4 또는 Tools 메뉴 | MQL5 EA 코드 작성과 컴파일 |
| Strategy Tester | Ctrl+R 또는 View 메뉴 | EA 백테스트와 최적화 실행 |
MetaTrader 5 공식 EA 실행 문서 새 탭는 EA를 Navigator 창에서 차트로 드래그하거나 더블클릭해 실행할 수 있다고 설명합니다. 또한 AutoTrading 권한이 꺼져 있으면 EA가 거래를 수행하지 못합니다. 초보자가 가장 자주 막히는 지점이 이 두 가지입니다.


오늘 사용할 예시 전략
이번 예시는 수익을 내기 위한 추천 전략이 아닙니다. MT5 자동매매 구조를 배우기 위한 가장 단순한 예제이며, 지금은 전략을 직접 설계할 필요가 없습니다.
규칙은 다음과 같습니다.
| 조건 | 행동 |
|---|---|
| 직전 완료 캔들이 양봉 | 매수 포지션을 엽니다 |
| 직전 완료 캔들이 음봉 | 매도 포지션을 엽니다 |
| 이미 반대 포지션이 있으면 | 같은 심볼에서 선택된 포지션의 MagicNumber가 이 EA와 같을 때만 청산을 요청합니다. 헤징 계좌의 여러 포지션은 모두 처리하지 않습니다 |
| 손절과 익절 | 입력값으로 정한 포인트만큼 설정합니다 |
| 거래 수량 | 입력값 Lots로 정합니다 |
이 전략은 일부러 단순하게 만들었습니다. 직전 캔들이 양봉이면 매수, 음봉이면 매도한다는 방식은 좋은 전략이라고 보기 어렵습니다. 하지만 첫 실습에서는 전략 성능보다 파일 생성, 컴파일, 차트 부착, 권한 확인, 로그 확인이 먼저입니다.
MetaEditor에서 EA 파일 만들기
MT5 데스크톱을 실행한 상태에서 다음 순서로 진행합니다.
이번 단계에서는 코드를 처음부터 작성하지 않습니다. 파일을 만들고, 예제 코드를 붙여 넣고, 컴파일하는 흐름만 연습합니다.
- 키보드에서
F4를 누릅니다. - MetaEditor가 열리면 왼쪽 위
File을 클릭합니다. New를 선택합니다.Expert Advisor (template)또는Expert Advisor를 선택합니다.- 이름은
Permact_First_Candle_EA로 입력합니다. - 생성된 기본 코드가 보이면 전체를 지우지 말고, 아래 전체 예시 코드로 교체합니다.
F7을 눌러 Compile합니다.- 아래쪽 결과 창에서
0 errors, 0 warnings가 보이는지 확인합니다.
MetaTrader 5 공식 MetaEditor 문서 새 탭는 MetaEditor가 MQL5 소스 코드를 만들고, 편집하고, 컴파일하고, 디버깅하는 개발 환경이라고 설명합니다. 첫 단계에서는 MQL5를 깊게 이해하지 않아도 됩니다. “코드를 붙여 넣고 컴파일해서 .ex5 실행 파일을 만든다”는 흐름만 익히면 됩니다.

첫 EA 예시 코드: 전체 복사용
아래 코드는 교육용 예시입니다. MetaEditor에서 만든 기본 템플릿과 비슷한 형태를 유지하면서 필요한 매매 로직만 추가했습니다. 코드 블록 전체를 복사해서 `Permact_First_Candle_EA.mq5`에 붙여 넣은 뒤 F7로 컴파일하면 됩니다.
복사가 불편하면 permact-first-candle-ea.mq5 원본 파일을 내려받아 MetaEditor의 Experts 폴더에 넣어도 됩니다.
이번 단계의 성공 기준은 코드 전체를 이해하는 것이 아니라 전체 복사 → 붙여넣기 → F7 컴파일 → 0 errors 확인을 완료하는 것입니다.//+------------------------------------------------------------------+
//| Permact_First_Candle_EA.mq5 |
//| Copyright 2026, Permact |
//| https://permact.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Permact"
#property link "https://permact.com"
#property version "1.10"
#include <Trade/Trade.mqh>
CTrade trade;
input double Lots = 0.01;
input int StopLossPoints = 300;
input int TakeProfitPoints = 600;
input int MinStopBufferPoints = 50;
input ulong MagicNumber = 20260708;
datetime lastBarTime = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
trade.SetExpertMagicNumber(MagicNumber);
trade.SetAsyncMode(false);
if (!trade.SetTypeFillingBySymbol(_Symbol))
{
Print("Initialization failed: unable to select the filling policy for ", _Symbol);
return(INIT_FAILED);
}
Print("Permact first candle EA started");
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
Print("Permact first candle EA stopped. Reason: ", reason);
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
datetime currentBarTime = iTime(_Symbol, _Period, 0);
if (currentBarTime == 0 || currentBarTime == lastBarTime)
return;
lastBarTime = currentBarTime;
if (Bars(_Symbol, _Period) < 10)
return;
double previousOpen = iOpen(_Symbol, _Period, 1);
double previousClose = iClose(_Symbol, _Period, 1);
if (previousOpen == 0 || previousClose == 0)
return;
if (previousClose > previousOpen)
{
CloseSellPosition();
if (!PositionSelect(_Symbol))
OpenBuy();
}
if (previousClose < previousOpen)
{
CloseBuyPosition();
if (!PositionSelect(_Symbol))
OpenSell();
}
//---
}
//+------------------------------------------------------------------+
//| Trade function |
//+------------------------------------------------------------------+
void OnTrade()
{
//---
//---
}
void OpenBuy()
{
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if (bid <= 0 || ask <= 0)
return;
int slPoints = EffectiveInitialStopPoints(StopLossPoints);
int tpPoints = EffectiveInitialStopPoints(TakeProfitPoints);
double sl = 0.0;
double tp = 0.0;
if (slPoints > 0)
sl = AlignPriceDown(bid - slPoints * _Point);
if (tpPoints > 0)
tp = AlignPriceUp(ask + tpPoints * _Point);
bool requestBuilt = trade.Buy(Lots, _Symbol, 0.0, sl, tp, "Permact candle buy");
TradeRequestCompleted(requestBuilt, "Buy");
}
void OpenSell()
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if (bid <= 0 || ask <= 0)
return;
int slPoints = EffectiveInitialStopPoints(StopLossPoints);
int tpPoints = EffectiveInitialStopPoints(TakeProfitPoints);
double sl = 0.0;
double tp = 0.0;
if (slPoints > 0)
sl = AlignPriceUp(ask + slPoints * _Point);
if (tpPoints > 0)
tp = AlignPriceDown(bid - tpPoints * _Point);
bool requestBuilt = trade.Sell(Lots, _Symbol, 0.0, sl, tp, "Permact candle sell");
TradeRequestCompleted(requestBuilt, "Sell");
}
int EffectiveInitialStopPoints(const int requestedPoints)
{
if (requestedPoints <= 0)
return 0;
int stopLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
int bufferPoints = MinStopBufferPoints > 0 ? MinStopBufferPoints : 0;
int minimumPoints = stopLevel + bufferPoints;
if (requestedPoints < minimumPoints)
return minimumPoints;
return requestedPoints;
}
double AlignPriceDown(const double price)
{
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
if (tickSize <= 0.0)
tickSize = _Point;
return NormalizeDouble(MathFloor(price / tickSize) * tickSize, _Digits);
}
double AlignPriceUp(const double price)
{
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
if (tickSize <= 0.0)
tickSize = _Point;
return NormalizeDouble(MathCeil(price / tickSize) * tickSize, _Digits);
}
bool TradeRequestCompleted(const bool requestBuilt, const string action)
{
uint retcode = trade.ResultRetcode();
ulong deal = trade.ResultDeal();
ulong order = trade.ResultOrder();
if (requestBuilt && retcode == TRADE_RETCODE_DONE && deal > 0)
return true;
if (retcode == TRADE_RETCODE_DONE_PARTIAL)
{
Print(action, " partially filled and requires reconciliation. Retcode: ", retcode, " ",
trade.ResultRetcodeDescription(), ", deal: ", deal, ", order: ", order);
return false;
}
if (retcode == TRADE_RETCODE_PLACED)
{
Print(action, " was placed but is not final; reconciliation is required. Retcode: ", retcode, " ",
trade.ResultRetcodeDescription(), ", deal: ", deal, ", order: ", order);
return false;
}
if (requestBuilt && retcode == TRADE_RETCODE_DONE && deal == 0)
{
Print(action, " returned DONE without a deal ticket; reconciliation is required. Order: ", order);
return false;
}
Print(action, " failed. Retcode: ", retcode, " ", trade.ResultRetcodeDescription(),
", deal: ", deal, ", order: ", order);
return false;
}
void CloseBuyPosition()
{
if (!PositionSelect(_Symbol))
return;
long currentType = PositionGetInteger(POSITION_TYPE);
long currentMagic = PositionGetInteger(POSITION_MAGIC);
if (currentType != POSITION_TYPE_BUY)
return;
if (currentMagic != (long)MagicNumber)
{
Print("Skip close: buy position belongs to another strategy. Magic: ", currentMagic);
return;
}
ulong ticket = (ulong)PositionGetInteger(POSITION_TICKET);
bool requestBuilt = trade.PositionClose(ticket);
if (TradeRequestCompleted(requestBuilt, "Close buy") && PositionSelectByTicket(ticket))
Print("Close buy returned a deal but the position remains open; reconciliation is required. Ticket: ", ticket);
}
void CloseSellPosition()
{
if (!PositionSelect(_Symbol))
return;
long currentType = PositionGetInteger(POSITION_TYPE);
long currentMagic = PositionGetInteger(POSITION_MAGIC);
if (currentType != POSITION_TYPE_SELL)
return;
if (currentMagic != (long)MagicNumber)
{
Print("Skip close: sell position belongs to another strategy. Magic: ", currentMagic);
return;
}
ulong ticket = (ulong)PositionGetInteger(POSITION_TICKET);
bool requestBuilt = trade.PositionClose(ticket);
if (TradeRequestCompleted(requestBuilt, "Close sell") && PositionSelectByTicket(ticket))
Print("Close sell returned a deal but the position remains open; reconciliation is required. Ticket: ", ticket);
}
//+------------------------------------------------------------------+MQL5 CTrade 공식 Reference 새 탭는 CTrade 클래스를 매매 작업을 쉽게 수행하기 위한 클래스라고 설명합니다. 위 코드에서는 Buy, Sell, PositionClose를 사용해 첫 자동매매 흐름을 최소한으로 보여 줍니다.
실습 전에 알아둘 안전 한계
이 코드는 구조를 관찰하기 위한 데모·백테스트 전용 예제입니다. 실계좌용 전략이 아닙니다.
- 청산 전에 선택된 포지션의
POSITION_MAGIC이 이 EA의MagicNumber와 같은지 확인하고, 다르면 건드리지 않습니다. - 다만 심볼별 포지션 하나만 가정합니다. 여러 포지션을 동시에 보유할 수 있는 헤징 계좌에서는 티켓 전체를 순회하지 않습니다.
- 심볼이 허용하는 filling mode를 초기화하고, 주문 요청 뒤 서버
ResultRetcode()와 deal·order 번호를 확인합니다.PLACED, 부분체결, deal 없는DONE은 완료로 보지 않고 재조정이 필요한 상태로 기록합니다. - 상품별 최소·최대 거래량과 volume step, 스프레드 제한, 거래 시간 필터, 일일 손실 한도, 재접속 복구를 구현하지 않았습니다.
기존 수동 포지션이나 다른 EA 포지션이 없는 깨끗한 데모 심볼에서만 실습하세요.
코드에서 꼭 알아야 할 부분
처음부터 모든 줄을 이해할 필요는 없습니다. 아래 개념만 먼저 잡으면 됩니다.
| 코드 개념 | 의미 |
|---|---|
OnInit() | EA가 차트에 붙을 때 한 번 실행 |
OnTick() | 새 가격 틱이 들어올 때마다 실행 |
iOpen, iClose | 직전 완료 캔들의 시가와 종가를 가져옴 |
previousClose > previousOpen | 직전 캔들이 양봉인지 확인 |
previousClose < previousOpen | 직전 캔들이 음봉인지 확인 |
trade.Buy, trade.Sell | 매수·매도 주문 요청 |
MagicNumber | EA가 낸 주문을 구분하는 번호 |
POSITION_MAGIC | 청산 대상이 이 EA 소유인지 확인 |
SYMBOL_TRADE_STOPS_LEVEL | 브로커의 최소 손절·익절 거리 확인 |
SYMBOL_TRADE_TICK_SIZE | 주문 가격을 심볼의 유효한 가격 간격에 맞춤 |
ResultRetcode() | 서버가 주문 요청을 어떻게 처리했는지 확인 |
MinStopBufferPoints는 NAS100, XAUUSD 같은 CFD에서 초기 손절·익절 가격에 추가하는 여유값입니다. 코드는 SYMBOL_TRADE_STOPS_LEVEL보다 요청 거리가 짧으면 여유값을 더한 거리로 보정하고, 가격을 SYMBOL_TRADE_TICK_SIZE에 맞춰 손절은 바깥 방향, 익절은 목표 방향으로 정렬합니다. SYMBOL_TRADE_FREEZE_LEVEL은 초기 stop 거리와 합치지 않습니다. 이후 기존 주문·포지션을 수정·취소·청산할 때는 서버 규칙과 TRADE_RETCODE_FROZEN 응답을 별도로 확인해야 합니다.
컴파일 에러가 날 때 보는 순서
컴파일 에러가 나면 코드 전체가 틀렸다고 생각하기 쉽지만, 대부분은 붙여넣기 과정에서 빠진 글자나 괄호 문제입니다.
| 증상 | 확인할 것 | 조치 |
|---|---|---|
Trade/Trade.mqh 관련 에러 | include 줄 철자 | #include <Trade/Trade.mqh> 그대로인지 확인 |
| 중괄호 에러 | {와 } 짝 | 코드 일부를 지우지 않았는지 확인 |
| 세미콜론 에러 | 줄 끝의 ; | 빠진 줄이 있는지 확인 |
0 errors, 0 warnings가 아님 | Errors 창 | 에러 줄을 더블클릭해 이동 |
| Navigator에 EA가 안 보임 | 저장 위치 | Experts 폴더 아래인지 확인 |
처음에는 코드 일부만 고치려 하지 말고 전체 코드를 다시 붙여 넣는 편이 빠를 때가 많습니다.
MT5 Navigator에서 EA 확인하기
컴파일이 끝났다면 MT5로 돌아갑니다. Navigator 창의 Expert Advisors 아래에 Permact_First_Candle_EA가 보여야 합니다. 보이지 않으면 Navigator에서 우클릭한 뒤 Refresh를 누릅니다.
확인 순서는 다음과 같습니다.
- MT5로 돌아갑니다.
- 왼쪽 아래 Navigator를 찾습니다.
Expert Advisors를 펼칩니다.Permact_First_Candle_EA가 보이는지 확인합니다.- 보이지 않으면 Navigator에서 우클릭 후
Refresh를 누릅니다. - 그래도 없으면 MetaEditor에서 파일 저장 위치를 다시 확인합니다.
EA는 .mq5 파일 자체가 아니라 컴파일된 .ex5 파일로 실행됩니다. 그래서 MetaEditor에서 F7 컴파일이 끝나야 MT5에서 실행할 수 있습니다.
데모 차트에 EA 붙이기
이제 데모 차트에 EA를 붙입니다.
- MT5가 데모 계좌에 로그인되어 있는지 확인합니다.
Market Watch에서 테스트할 심볼을 고릅니다.- 심볼을 더블클릭하거나 차트로 엽니다.
- 처음에는
H1또는D1처럼 너무 짧지 않은 시간봉을 선택합니다. - Navigator에서
Permact_First_Candle_EA를 차트로 드래그합니다. - 설정 창이 뜨면
Common탭에서 자동매매 허용 관련 항목을 확인합니다. Inputs탭에서 입력값을 확인합니다.OK를 누릅니다.- 차트 오른쪽 위에 EA 이름이 표시되는지 확인합니다.
- 아래
Toolbox의Experts와Journal탭을 봅니다.
여기서 중요한 것은 EA가 차트에 붙자마자 무조건 주문을 넣는 것은 아니라는 점입니다. 이 예시 EA는 새 봉이 생길 때 직전 캔들이 양봉인지 음봉인지 확인합니다. 차트에 붙였는데 아무 주문도 없을 수 있고, 그것이 정상일 수 있습니다.
같은 실습을 다시 확인할 수 있도록 Help → About의 MT5 터미널 빌드, 운영체제, 브로커·서버, 데모 계좌 유형, 심볼, 시간봉, EA 파일 버전, Inputs 값을 함께 기록하세요. 계좌번호나 비밀번호 같은 인증 정보는 기록표나 화면 캡처에 남기지 않습니다.

Inputs 값은 이렇게 봅니다
| 입력값 | 의미 | 처음 권장 |
|---|---|---|
Lots | 주문 수량 | 0.01 |
StopLossPoints | 손절 거리 | 상품별로 조정 |
TakeProfitPoints | 익절 거리 | 상품별로 조정 |
MinStopBufferPoints | 최소 stop level보다 더 둘 여유 | 50부터 시작 |
MagicNumber | EA 주문 식별 번호 | 기본값 유지 |
Lots는 무조건 작게 시작합니다. 데모라고 해도 처음부터 큰 lot을 넣으면 손익이 커 보이고 전략이 좋아 보이는 착시가 생깁니다. 첫 실습의 목적은 수익금이 아니라 EA가 정상적으로 붙고, 로그가 어떻게 찍히는지 보는 것입니다.
AutoTrading 권한 확인
MT5 자동매매가 되지 않을 때는 전략보다 권한 문제가 더 흔합니다.
| 위치 | 확인할 것 | 꺼져 있으면 생기는 일 |
|---|---|---|
| 상단 도구막대 | Algo Trading 또는 AutoTrading 버튼 | 모든 EA의 주문 실행이 막힐 수 있음 |
| EA 설정 Common 탭 | 해당 EA의 자동매매 허용 | EA는 계산하지만 주문을 못 보낼 수 있음 |
| Tools → Options → Expert Advisors | 플랫폼 전체 자동매매 허용 | EA별 허용을 켜도 주문이 막힐 수 있음 |
| 계좌 전환 옵션 | 계좌 변경 시 자동매매 차단 | 데모에서 실계좌로 바꿀 때 보호 장치로 작동 |
초보자는 “차트 오른쪽 위에 EA 이름이 보이면 끝”이라고 생각하기 쉽습니다. 하지만 EA 이름이 보이는 것과 주문 권한이 켜진 것은 다릅니다. 상단 버튼, EA별 설정, 전체 옵션을 모두 확인해야 합니다.
Journal과 Experts 탭에서 보는 메시지
EA를 차트에 붙였다면 아래 Toolbox에서 Experts와 Journal 탭을 확인합니다.
| 메시지 유형 | 의미 | 대응 |
|---|---|---|
started | EA가 시작됨 | 정상 |
stopped | EA가 종료됨 | 차트에서 제거했거나 설정 변경 |
auto trading disabled by client | 자동매매 권한이 꺼짐 | Algo Trading 버튼과 옵션 확인 |
invalid stops | 가격 방향·거리·호가 단위 또는 서버 규칙 위반 | Bid/Ask, stop level, tick size, retcode를 함께 기록하고 순서대로 확인 |
not enough money | 증거금 부족 | lot 축소 |
market closed | 거래 시간 아님 | 심볼 거래 시간 확인 |
자동매매는 화면보다 로그가 더 중요합니다. “주문이 왜 안 들어가지?”라는 질문의 답은 대부분 Journal 또는 Experts 탭에 있습니다.
오늘 단계에서 성공 기준
이번 글에서 성공 기준은 수익이 아닙니다. 아래 항목이 되면 성공입니다.
| 체크 | 내용 |
|---|---|
| MetaEditor에서 EA 파일을 만들었다 | |
F7 컴파일 후 0 errors, 0 warnings를 확인했다 | |
| MT5 Navigator에서 EA 이름을 찾았다 | |
| 데모 차트에 EA를 붙였다 | |
| Inputs 값을 확인했다 | |
| AutoTrading 권한 위치를 알았다 | |
| Experts와 Journal 탭을 열어 봤다 |
이 단계까지 왔다면 이제 EA 파일은 준비됐습니다. 하지만 아직 전략이 검증된 것은 아닙니다. 다음 단계는 이 EA를 과거 데이터에 돌려 보고, 어느 구간에서 손실이 반복되는지 확인하는 것입니다.
다음 글로 이어가기
다음 글에서는 MT5 Strategy Tester 백테스트 가이드를 다룹니다. Expert, Symbol, Timeframe, Date, Deposit, Leverage를 설정하고, Visual mode에서 주문 흐름을 확인하고, invalid stops 같은 오류를 읽고, 결과 리포트를 어떻게 의심해야 하는지 정리합니다.