#property description "거래 요청 전송을 위한 Expert Advisor "
" OrderSendAsync() 함수를 이용한 \r\n"
#property description "다음을 사용하여 거래 이벤트를 핸들링"
" OnTrade() 및 OnTradeTransaction() 핸들러 함수가 표시됩니다\r\n"
#property description "Expert Advisor 매개 변수는 Magic Number 설정을 허용합니다"
" (unique ID) "
#property description "그리고 전문가 로그에 메시지를 표시하는 모드. 모든 세부 정보가 기본적으로 표시됩니다.\r\n"
//--- 입력 매개 변수
input int MagicNumber=1234567; // Expert Advisor ID
input bool DescriptionModeFull=true; // 상세 출력 모드
//--- HistorySelect() 호출에 사용하기 위한 변수
datetime history_start;
//+------------------------------------------------------------------+
//| Expert 초기화 함수 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 오토트레이딩이 가능한지 확인
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Alert("터미널 내 오토트레이딩이 비활성화되면 Expert Advisor가 제거됩니다.");
ExpertRemove();
return(-1);
}
//--- 실제 계정에서 거래할 수 없음
if(AccountInfoInteger(ACCOUNT_TRADE_MODE)==ACCOUNT_TRADE_MODE_REAL)
{
Alert("Expert Advisor는 실제 계정으로 거래할 수 없습니다!");
ExpertRemove();
return(-2);
}
//--- 이 계정으로 거래할 수 있는지 확인(예: 투자자 비밀번호를 사용하는 경우 거래 불가).
if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
{
Alert("이 계정에서의 거래는 불가능합니다");
ExpertRemove();
return(-3);
}
//--- 거래 내역 수신을 위한 Expert Advisor의 런칭 시간을 저장
history_start=TimeCurrent();
//---
CreateBuySellButtons();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert 초기화 취소 함수 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- 모든 그래픽 개체 삭제
ObjectDelete(0,"Buy");
ObjectDelete(0,"Sell");
//---
}
//+------------------------------------------------------------------+
//| TradeTransaction 함수 |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
//--- 거래 이벤트의 핸들러 기능의 이름을 딴 헤더
Print("=> ",__FUNCTION__," at ",TimeToString(TimeCurrent(),TIME_SECONDS));
//--- 열거값으로 트랜잭션 유형 수신
ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- 거래가 요청 처리의 결과인 경우
if(type==TRADE_TRANSACTION_REQUEST)
{
//--- 거래명 표시
Print(EnumToString(type));
//--- 그런 다음 처리된 요청에 대한 문자열 설명을 표시합니다.
Print("------------RequestDescription\r\n",
RequestDescription(request,DescriptionModeFull));
//--- 요청 결과에 대한 설명 표시
Print("------------ ResultDescription\r\n",
TradeResultDescription(result,DescriptionModeFull));
}
else // 다른 유형의 트랜잭션에 대한 전체 설명을 표시합니다
{
Print("------------ TransactionDescription\r\n",
TransactionDescription(trans,DescriptionModeFull));
}
//---
}
//+------------------------------------------------------------------+
//| 거래 함수 |
//+------------------------------------------------------------------+
void OnTrade()
{
//--- 거래 계정 상태를 저장하기 위한 정적 멤버
static int prev_positions=0,prev_orders=0,prev_deals=0,prev_history_orders=0;
//--- 거래 내역 요청
bool update=HistorySelect(history_start,TimeCurrent());
PrintFormat("HistorySelect(%s , %s) = %s",
TimeToString(history_start),TimeToString(TimeCurrent()),(string)update);
//--- 거래 이벤트의 핸들러 기능의 이름을 딴 헤더
Print("=> ",__FUNCTION__," at ",TimeToString(TimeCurrent(),TIME_SECONDS));
//--- 핸들러 이름 및 처리 당시의 주문 수를 표시합니다
int curr_positions=PositionsTotal();
int curr_orders=OrdersTotal();
int curr_deals=HistoryOrdersTotal();
int curr_history_orders=HistoryDealsTotal();
//--- 주문 수, 포지션, 거래 및 변경 사항을 괄호 안에 표시합니다
PrintFormat("PositionsTotal() = %d (%+d)",
curr_positions,(curr_positions-prev_positions));
PrintFormat("OrdersTotal() = %d (%+d)",
curr_orders,curr_orders-prev_orders);
PrintFormat("HistoryOrdersTotal() = %d (%+d)",
curr_deals,curr_deals-prev_deals);
PrintFormat("HistoryDealsTotal() = %d (%+d)",
curr_history_orders,curr_history_orders-prev_history_orders);
//--- 보다 편리하게 로그를 볼 수 있도록 줄 바꿈 삽입
Print("");
//--- 계정 상태 저장
prev_positions=curr_positions;
prev_orders=curr_orders;
prev_deals=curr_deals;
prev_history_orders=curr_history_orders;
//---
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- CHARTEVENT_CLICK 이벤트 핸들링 ("차트 클릭")
if(id==CHARTEVENT_OBJECT_CLICK)
{
Print("=> ",__FUNCTION__,": sparam = ",sparam);
//--- 딜의 최소량
double volume_min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
//--- "매수" 버튼이 눌린다면 매수합니다
if(sparam=="Buy")
{
PrintFormat("Buy %s %G lot",_Symbol,volume_min);
BuyAsync(volume_min);
//--- 버튼 누름취소
ObjectSetInteger(0,"Buy",OBJPROP_STATE,false);
}
//--- "매도" 버튼이 눌렸다면 매도합니다
if(sparam=="Sell")
{
PrintFormat("Sell %s %G lot",_Symbol,volume_min);
SellAsync(volume_min);
//--- 버튼 누름취소
ObjectSetInteger(0,"Sell",OBJPROP_STATE,false);
}
ChartRedraw();
}
//---
}
//+------------------------------------------------------------------+
//| 트랜잭션의 텍스트 설명을 반환합니다 |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans,
const bool detailed=true)
{
//--- 함수로부터 반환될 수 있는 문자열 준비
string desc=EnumToString(trans.type)+"\r\n";
//--- 가능한 모든 데이터가 상세 모드로 추가됨
if(detailed)
{
desc+="Symbol: "+trans.symbol+"\r\n";
desc+="Deal ticket: "+(string)trans.deal+"\r\n";
desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
desc+="Order ticket: "+(string)trans.order+"\r\n";
desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
desc+="Price: "+StringFormat("%G",trans.price)+"\r\n";
desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";
}
//--- 받은 문자열 반환
return desc;
}
//+------------------------------------------------------------------+
//| 거래 요청에 대한 텍스트 설명을 반환합니다 |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request,
const bool detailed=true)
{
//--- 함수로부터 반환될 수 있는 문자열 준비
string desc=EnumToString(request.action)+"\r\n";
//--- 세부 모드에서 사용 가능한 모든 데이터 추가
if(detailed)
{
desc+="Symbol: "+request.symbol+"\r\n";
desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
desc+="Order ticket: "+(string)request.order+"\r\n";
desc+="Order type: "+EnumToString(request.type)+"\r\n";
desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
desc+="Comment: "+request.comment+"\r\n";
}
//--- 받은 문자열 반환
return desc;
}
//+------------------------------------------------------------------+
//| 요청 처리 결과의 텍스트 설명을 반환합니다 |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result,
const bool detailed=true)
{
//--- 함수로부터 반환된 문자열 준비
string desc="Retcode "+(string)result.retcode+"\r\n";
//--- 세부 모드에서 사용 가능한 모든 데이터 추가
if(detailed)
{
desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
desc+="Order ticket: "+(string)result.order+"\r\n";
desc+="Deal ticket: "+(string)result.deal+"\r\n";
desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
desc+="Comment: "+result.comment+"\r\n";
}
//--- 받은 문자열 반환
return desc;
}
//+------------------------------------------------------------------+
//| 구매 및 판매를 위한 두 가지 버튼 생성 |
//+------------------------------------------------------------------+
void CreateBuySellButtons()
{
//--- 이름이 "Buy"인 개체 확인
if(ObjectFind(0,"Buy")>=0)
{
//--- 발견된 개체가 버튼이 아닌 경우 삭제
if(ObjectGetInteger(0,"Buy",OBJPROP_TYPE)!=OBJ_BUTTON)
ObjectDelete(0,"Buy");
}
else
ObjectCreate(0,"Buy",OBJ_BUTTON,0,0,0); // "Buy" 버튼 생성
//--- "Buy" 버튼 구성
ObjectSetInteger(0,"Buy",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
ObjectSetInteger(0,"Buy",OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,"Buy",OBJPROP_YDISTANCE,50);
ObjectSetInteger(0,"Buy",OBJPROP_XSIZE,70);
ObjectSetInteger(0,"Buy",OBJPROP_YSIZE,30);
ObjectSetString(0,"Buy",OBJPROP_TEXT,"Buy");
ObjectSetInteger(0,"Buy",OBJPROP_COLOR,clrRed);
//--- 이름이 "Sell"인 개체의 존재 여부 확인
if(ObjectFind(0,"Sell")>=0)
{
//--- 발견된 개체가 버튼이 아닌 경우 삭제
if(ObjectGetInteger(0,"Sell",OBJPROP_TYPE)!=OBJ_BUTTON)
ObjectDelete(0,"Sell");
}
else
ObjectCreate(0,"Sell",OBJ_BUTTON,0,0,0); // "Sell" 버튼 생성
//--- "Sell" 버튼 구성
ObjectSetInteger(0,"Sell",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
ObjectSetInteger(0,"Sell",OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,"Sell",OBJPROP_YDISTANCE,100);
ObjectSetInteger(0,"Sell",OBJPROP_XSIZE,70);
ObjectSetInteger(0,"Sell",OBJPROP_YSIZE,30);
ObjectSetString(0,"Sell",OBJPROP_TEXT,"Sell");
ObjectSetInteger(0,"Sell",OBJPROP_COLOR,clrBlue);
//--- 즉시 버튼을 표시하도록 차트 강제 업데이트를 수행합니다
ChartRedraw();
//---
}
//+------------------------------------------------------------------+
//| OrderSendAsync() 비동기 함수를 사용하여 구매 |
//+------------------------------------------------------------------+
void BuyAsync(double volume)
{
//--- 요청 준비
MqlTradeRequest req={0};
req.action =TRADE_ACTION_DEAL;
req.symbol =_Symbol;
req.magic =MagicNumber;
req.volume =0.1;
req.type =ORDER_TYPE_BUY;
req.price =SymbolInfoDouble(req.symbol,SYMBOL_ASK);
req.deviation =10;
req.comment ="Buy using OrderSendAsync()";
MqlTradeResult res={0};
if(!OrderSendAsync(req,res))
{
Print(__FUNCTION__,": error ",GetLastError(),", retcode = ",res.retcode);
}
//---
}
//+------------------------------------------------------------------+
//| 비동기식 OrderSendAsync() 함수를 사용하여 판매 |
//+------------------------------------------------------------------+
void SellAsync(double volume)
{
//--- 요청 준비
MqlTradeRequest req={0};
req.action =TRADE_ACTION_DEAL;
req.symbol =_Symbol;
req.magic =MagicNumber;
req.volume =0.1;
req.type =ORDER_TYPE_SELL;
req.price =SymbolInfoDouble(req.symbol,SYMBOL_BID);
req.deviation =10;
req.comment ="Sell using OrderSendAsync()";
MqlTradeResult res={0};
if(!OrderSendAsync(req,res))
{
Print(__FUNCTION__,": error ",GetLastError(),", retcode = ",res.retcode);
}
//---
}
//+------------------------------------------------------------------+
|