363 lines
30 KiB
Plaintext
363 lines
30 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| Daydream(barabashkakvn's edition).mq5 |
|
|
//+------------------------------------------------------------------+
|
|
#property version "1.000"
|
|
//---
|
|
#include <Trade\PositionInfo.mqh>
|
|
#include <Trade\Trade.mqh>
|
|
#include <Trade\SymbolInfo.mqh>
|
|
CPositionInfo m_position; // trade position object
|
|
CTrade m_trade; // trading object
|
|
CSymbolInfo m_symbol; // symbol info object
|
|
//--- input parameters
|
|
input double InpLots = 0.1; // Lots
|
|
input ushort InpTakeProfit = 50; // Virtual Take Profit (in pips)
|
|
input uchar InpChannel = 25; // Channel (in Bars)
|
|
|
|
input ulong m_magic=3463424; // magic number
|
|
//---
|
|
ulong m_slippage=10; // slippage
|
|
|
|
double ExtTakeProfit=0.0;
|
|
|
|
double m_adjusted_point; // point value adjusted for 3 or 5 points
|
|
long m_last_date_IN=-1;
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
//---
|
|
if(!m_symbol.Name(Symbol())) // sets symbol name
|
|
return(INIT_FAILED);
|
|
RefreshRates();
|
|
|
|
string err_text="";
|
|
if(!CheckVolumeValue(InpLots,err_text))
|
|
{
|
|
Print(__FUNCTION__,", ERROR: ",err_text);
|
|
return(INIT_PARAMETERS_INCORRECT);
|
|
}
|
|
//---
|
|
m_trade.SetExpertMagicNumber(m_magic);
|
|
m_trade.SetMarginMode();
|
|
m_trade.SetTypeFillingBySymbol(m_symbol.Name());
|
|
m_trade.SetDeviationInPoints(m_slippage);
|
|
//--- tuning for 3 or 5 digits
|
|
int digits_adjust=1;
|
|
if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
|
|
digits_adjust=10;
|
|
m_adjusted_point=m_symbol.Point()*digits_adjust;
|
|
|
|
ExtTakeProfit=InpTakeProfit *m_adjusted_point;
|
|
//---
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
//---
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
//---
|
|
if(!RefreshRates())
|
|
return;
|
|
bool closing=false;
|
|
|
|
for(int i=PositionsTotal()-1;i>=0;i--)
|
|
if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
|
|
if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
|
|
{
|
|
if(m_position.PositionType()==POSITION_TYPE_BUY)
|
|
{
|
|
if(m_position.PriceCurrent()-m_position.PriceOpen()>ExtTakeProfit)
|
|
{
|
|
if(!m_trade.PositionClose(m_position.Ticket()))
|
|
Print("ERROR close BUY: ",m_trade.ResultRetcode());
|
|
closing=true;
|
|
}
|
|
}
|
|
if(m_position.PositionType()==POSITION_TYPE_SELL)
|
|
{
|
|
if(m_position.PriceOpen()-m_position.PriceCurrent()>ExtTakeProfit)
|
|
{
|
|
if(!m_trade.PositionClose(m_position.Ticket()))
|
|
Print("ERROR close SELL: ",m_trade.ResultRetcode());
|
|
closing=true;
|
|
}
|
|
}
|
|
}
|
|
if(closing)
|
|
return;
|
|
//---
|
|
double HighestValue=iHigh(m_symbol.Name(),Period(),iHighest(m_symbol.Name(),Period(),MODE_HIGH,InpChannel,1));
|
|
double LowestValue=iLow(m_symbol.Name(),Period(),iLowest(m_symbol.Name(),Period(),MODE_LOW,InpChannel,1));
|
|
double close_0=iClose(m_symbol.Name(),Period(),0);
|
|
datetime time_0=iTime(m_symbol.Name(),Period(),0);
|
|
|
|
if(close_0<LowestValue && m_last_date_IN<time_0)
|
|
{
|
|
ClosePositions(POSITION_TYPE_SELL);
|
|
OpenBuy(0.0,0.0);
|
|
return;
|
|
}
|
|
if(close_0>HighestValue && m_last_date_IN<time_0)
|
|
{
|
|
ClosePositions(POSITION_TYPE_BUY);
|
|
OpenSell(0.0,0.0);
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| TradeTransaction function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTradeTransaction(const MqlTradeTransaction &trans,
|
|
const MqlTradeRequest &request,
|
|
const MqlTradeResult &result)
|
|
{
|
|
//---
|
|
//--- get transaction type as enumeration value
|
|
ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
|
|
//--- if transaction is result of addition of the transaction in history
|
|
if(type==TRADE_TRANSACTION_DEAL_ADD)
|
|
{
|
|
long deal_ticket =0;
|
|
long deal_order =0;
|
|
long deal_time =0;
|
|
long deal_time_msc =0;
|
|
long deal_type =-1;
|
|
long deal_entry =-1;
|
|
long deal_magic =0;
|
|
long deal_reason =-1;
|
|
long deal_position_id =0;
|
|
double deal_volume =0.0;
|
|
double deal_price =0.0;
|
|
double deal_commission =0.0;
|
|
double deal_swap =0.0;
|
|
double deal_profit =0.0;
|
|
string deal_symbol ="";
|
|
string deal_comment ="";
|
|
string deal_external_id ="";
|
|
if(HistoryDealSelect(trans.deal))
|
|
{
|
|
deal_ticket =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
|
|
deal_order =HistoryDealGetInteger(trans.deal,DEAL_ORDER);
|
|
deal_time =HistoryDealGetInteger(trans.deal,DEAL_TIME);
|
|
deal_time_msc =HistoryDealGetInteger(trans.deal,DEAL_TIME_MSC);
|
|
deal_type =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
|
|
deal_entry =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
|
|
deal_magic =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
|
|
deal_reason =HistoryDealGetInteger(trans.deal,DEAL_REASON);
|
|
deal_position_id =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);
|
|
|
|
deal_volume =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
|
|
deal_price =HistoryDealGetDouble(trans.deal,DEAL_PRICE);
|
|
deal_commission =HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);
|
|
deal_swap =HistoryDealGetDouble(trans.deal,DEAL_SWAP);
|
|
deal_profit =HistoryDealGetDouble(trans.deal,DEAL_PROFIT);
|
|
|
|
deal_symbol =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
|
|
deal_comment =HistoryDealGetString(trans.deal,DEAL_COMMENT);
|
|
deal_external_id =HistoryDealGetString(trans.deal,DEAL_EXTERNAL_ID);
|
|
}
|
|
else
|
|
return;
|
|
if(deal_symbol==m_symbol.Name() && deal_magic==m_magic)
|
|
if(deal_entry==DEAL_ENTRY_IN)
|
|
m_last_date_IN=deal_time;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Refreshes the symbol quotes data |
|
|
//+------------------------------------------------------------------+
|
|
bool RefreshRates(void)
|
|
{
|
|
//--- refresh rates
|
|
if(!m_symbol.RefreshRates())
|
|
{
|
|
Print("RefreshRates error");
|
|
return(false);
|
|
}
|
|
//--- protection against the return value of "zero"
|
|
if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
|
|
return(false);
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Check the correctness of the position volume |
|
|
//+------------------------------------------------------------------+
|
|
bool CheckVolumeValue(double volume,string &error_description)
|
|
{
|
|
//--- minimal allowed volume for trade operations
|
|
double min_volume=m_symbol.LotsMin();
|
|
if(volume<min_volume)
|
|
{
|
|
if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
|
|
error_description=StringFormat("Объем меньше минимально допустимого SYMBOL_VOLUME_MIN=%.2f",min_volume);
|
|
else
|
|
error_description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
|
|
return(false);
|
|
}
|
|
//--- maximal allowed volume of trade operations
|
|
double max_volume=m_symbol.LotsMax();
|
|
if(volume>max_volume)
|
|
{
|
|
if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
|
|
error_description=StringFormat("Объем больше максимально допустимого SYMBOL_VOLUME_MAX=%.2f",max_volume);
|
|
else
|
|
error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
|
|
return(false);
|
|
}
|
|
//--- get minimal step of volume changing
|
|
double volume_step=m_symbol.LotsStep();
|
|
int ratio=(int)MathRound(volume/volume_step);
|
|
if(MathAbs(ratio*volume_step-volume)>0.0000001)
|
|
{
|
|
if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")
|
|
error_description=StringFormat("Объем не кратен минимальному шагу SYMBOL_VOLUME_STEP=%.2f, ближайший правильный объем %.2f",
|
|
volume_step,ratio*volume_step);
|
|
else
|
|
error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
|
|
volume_step,ratio*volume_step);
|
|
return(false);
|
|
}
|
|
error_description="Correct volume value";
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Close positions |
|
|
//+------------------------------------------------------------------+
|
|
void ClosePositions(const ENUM_POSITION_TYPE pos_type)
|
|
{
|
|
for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of current positions
|
|
if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
|
|
if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
|
|
if(m_position.PositionType()==pos_type) // gets the position type
|
|
m_trade.PositionClose(m_position.Ticket()); // close a position by the specified symbol
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Open Buy position |
|
|
//+------------------------------------------------------------------+
|
|
void OpenBuy(double sl,double tp)
|
|
{
|
|
sl=m_symbol.NormalizePrice(sl);
|
|
tp=m_symbol.NormalizePrice(tp);
|
|
//--- check volume before OrderSend to avoid "not enough money" error (CTrade)
|
|
double check_volume_lot=m_trade.CheckVolume(m_symbol.Name(),InpLots,m_symbol.Ask(),ORDER_TYPE_BUY);
|
|
|
|
if(check_volume_lot!=0.0)
|
|
{
|
|
if(check_volume_lot>=InpLots)
|
|
{
|
|
if(m_trade.Buy(InpLots,m_symbol.Name(),m_symbol.Ask(),sl,tp))
|
|
{
|
|
if(m_trade.ResultDeal()==0)
|
|
{
|
|
Print(__FUNCTION__,", #1 Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResultTrade(m_trade,m_symbol);
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", #2 Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResultTrade(m_trade,m_symbol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", #3 Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResultTrade(m_trade,m_symbol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", ERROR: method CheckVolume (",DoubleToString(check_volume_lot,2),") ",
|
|
"< Lots (",DoubleToString(InpLots,2),")");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", ERROR: method CheckVolume returned the value of \"0.0\"");
|
|
return;
|
|
}
|
|
//---
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Open Sell position |
|
|
//+------------------------------------------------------------------+
|
|
void OpenSell(double sl,double tp)
|
|
{
|
|
sl=m_symbol.NormalizePrice(sl);
|
|
tp=m_symbol.NormalizePrice(tp);
|
|
//--- check volume before OrderSend to avoid "not enough money" error (CTrade)
|
|
double check_volume_lot=m_trade.CheckVolume(m_symbol.Name(),InpLots,m_symbol.Bid(),ORDER_TYPE_SELL);
|
|
|
|
if(check_volume_lot!=0.0)
|
|
{
|
|
if(check_volume_lot>=InpLots)
|
|
{
|
|
if(m_trade.Sell(InpLots,m_symbol.Name(),m_symbol.Bid(),sl,tp))
|
|
{
|
|
if(m_trade.ResultDeal()==0)
|
|
{
|
|
Print(__FUNCTION__,", #1 Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResultTrade(m_trade,m_symbol);
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", #2 Sell -> true. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResultTrade(m_trade,m_symbol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", #3 Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
|
|
", description of result: ",m_trade.ResultRetcodeDescription());
|
|
PrintResultTrade(m_trade,m_symbol);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", ERROR: method CheckVolume (",DoubleToString(check_volume_lot,2),") ",
|
|
"< Lots (",DoubleToString(InpLots,2),")");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Print(__FUNCTION__,", ERROR: method CheckVolume returned the value of \"0.0\"");
|
|
return;
|
|
}
|
|
//---
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Print CTrade result |
|
|
//+------------------------------------------------------------------+
|
|
void PrintResultTrade(CTrade &trade,CSymbolInfo &symbol)
|
|
{
|
|
Print("File: ",__FILE__,", symbol: ",m_symbol.Name());
|
|
Print("Code of request result: "+IntegerToString(trade.ResultRetcode()));
|
|
Print("code of request result as a string: "+trade.ResultRetcodeDescription());
|
|
Print("Deal ticket: "+IntegerToString(trade.ResultDeal()));
|
|
Print("Order ticket: "+IntegerToString(trade.ResultOrder()));
|
|
Print("Volume of deal or order: "+DoubleToString(trade.ResultVolume(),2));
|
|
Print("Price, confirmed by broker: "+DoubleToString(trade.ResultPrice(),symbol.Digits()));
|
|
Print("Current bid price: "+DoubleToString(symbol.Bid(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultBid(),symbol.Digits()));
|
|
Print("Current ask price: "+DoubleToString(symbol.Ask(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultAsk(),symbol.Digits()));
|
|
Print("Broker comment: "+trade.ResultComment());
|
|
}
|
|
//+------------------------------------------------------------------+
|