Major changes for MT5 compatibility: - Replaced MT4 OrderSelect() with MT5 PositionGet/HistorySelect - Replaced MarketInfo() with SymbolInfoDouble/Integer - Replaced Bid/Ask/Digits/Point globals with function calls - Updated trade functions to use CTrade class - Changed ticket types from int to ulong - Replaced WindowExpertName() with MQLInfoString() - Replaced IsOptimization() with MQLInfoInteger() - Updated copyright to Garfield Heron / fetcherpay.com Note: Full grid logic needs comprehensive testing
1370 lines
44 KiB
Plaintext
1370 lines
44 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| OrdersEA.mq5 |
|
|
//| Garfield Heron |
|
|
//| https://fetcherpay.com|
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2024, Garfield Heron"
|
|
#property link "http://www.fetcherpay.com"
|
|
|
|
#define VERSION "Version 1.1 gh"
|
|
|
|
// WinAPI include removed - using native MT5 functions
|
|
|
|
// web.mq5 include removed - license check disabled
|
|
|
|
#define MAX_TRADES 600
|
|
#define MAX_LOG_TRADES 1200
|
|
//---- input parameters
|
|
|
|
extern string Email= "garfield@fetcherpay.com";
|
|
extern int MagicNum= 333;
|
|
extern double HIGH= 0;
|
|
extern double LOW= 0;
|
|
extern double Lots=0.1;
|
|
extern double Entry= 1;
|
|
extern double TP= 0.5;
|
|
extern int StopLoss=0;
|
|
extern int TRADE_RANGE= 50;
|
|
extern double LongLimit= 0;
|
|
extern double ShortLimit= 0;
|
|
extern string GetOut= "N";
|
|
extern string OpenNewTrades="Y";
|
|
extern bool Opposite= false;
|
|
extern int TakeProfitLevelPercent= 50;
|
|
extern int TakeProfitLevelDollarAmount= 2000;
|
|
extern bool Restart= true;
|
|
extern int EquityFactorPercent= 0;
|
|
extern int LotsFactorPercent= 0;
|
|
//extern string VACCodeT= "";
|
|
//extern string VACCodeH= "";
|
|
extern string HoldingAccount= "";
|
|
extern int BaseEquity= 10000;
|
|
extern bool Master= false;
|
|
extern string Version_4.1.1.beta="";
|
|
extern bool DiagnosticModeOn= false;
|
|
extern double moveRangeTrigger = 0.0;
|
|
|
|
int initialCycleEquity= 0;
|
|
int longs, shorts;
|
|
int longsTicket[MAX_TRADES];
|
|
int shortsTicket[MAX_TRADES];
|
|
int logTickets[MAX_LOG_TRADES];
|
|
int logTicketsTime[MAX_LOG_TRADES];
|
|
int logTicketsCounter;
|
|
int Levels;
|
|
double price[MAX_TRADES]; //The bid price of every order
|
|
int stoplevel;
|
|
bool bFirstTick= false;
|
|
int logId;
|
|
bool bEnableLongs;
|
|
bool bEnableShorts;
|
|
double tickValue;
|
|
int MaximalLoss;
|
|
int lastTicketSentOpen= 0, lastTicketSentClose= 0;
|
|
double longAvgPrice= 0, longAvgLots= 0;
|
|
double shortAvgPrice= 0, shortAvgLots= 0;
|
|
double longProfit= 0;
|
|
double shortProfit= 0;
|
|
|
|
bool bOpposite;
|
|
bool bInit= false;
|
|
int TakeProfit=0;
|
|
bool AboveHigh;
|
|
bool BelowLow;
|
|
int tradeLogId;
|
|
double closeOnProfit;
|
|
bool bGetOutOK, bOpenNewTradesOK;
|
|
int initEquity;
|
|
int lotDigits;
|
|
bool bWithdrawMailSent= false;
|
|
bool bGetOutHandled; // handles the first GetOut in the start and not in the init due to time limitations
|
|
int PingTimeMinutes= 240;
|
|
|
|
bool bValidSettings;
|
|
string errMsg;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
double CalcLots()
|
|
{
|
|
double tmp= (AccountEquity()-initEquity);
|
|
double a= EquityFactorPercent;
|
|
double b= LotsFactorPercent;
|
|
double lots;
|
|
|
|
if(0==EquityFactorPercent || 0==LotsFactorPercent)
|
|
lots= Lots;
|
|
else
|
|
{
|
|
a=initEquity*a/100;
|
|
|
|
b=b/100;
|
|
if(tmp>0)
|
|
tmp= MathPow(1+b,(tmp/a));
|
|
else
|
|
if(tmp<0)
|
|
tmp= MathPow(1-b,MathAbs(tmp/a));
|
|
else
|
|
tmp= 1;
|
|
|
|
Log("DBG tmp="+tmp+",a="+a+",b="+b+",AccountEquity()="+AccountEquity());
|
|
//double lots= NormalizeDouble(Lots*AccountEquity()/initEquity,1);
|
|
lots= NormalizeDouble(Lots*tmp,lotDigits);
|
|
if(lots<MarketInfo(Symbol(),MODE_MINLOT))
|
|
lots= MarketInfo(Symbol(),MODE_MINLOT);
|
|
}
|
|
|
|
if(lots<0)
|
|
Log("ERROR tmp="+tmp+",a="+a+",b="+b+",AccountEquity()="+AccountEquity());
|
|
Log("Equity="+AccountEquity()+",lots="+lots);
|
|
return(lots);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void AddTradeToLog(int ticket)
|
|
{
|
|
bool rc= false;
|
|
for(int i=0; i<logTicketsCounter; i++)
|
|
{
|
|
if(logTickets[i]==ticket)
|
|
{
|
|
rc= true;
|
|
break;
|
|
}
|
|
}
|
|
if(!rc && i<MAX_LOG_TRADES)
|
|
{
|
|
logTickets[logTicketsCounter]= ticket;
|
|
logTicketsTime[logTicketsCounter]= TimeCurrent();
|
|
logTicketsCounter++;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|
|
//| Send notification using native MT5 functions |
|
|
//+------------------------------------------------------------------+
|
|
void SendNotificationEx(string title, string subject)
|
|
{
|
|
if(!IsOptimization())
|
|
{
|
|
string msg = title + ": " + subject;
|
|
msg = msg + " | Price: " + DoubleToString(Bid, Digits);
|
|
msg = msg + " | Longs: " + IntegerToString(longs) + " @ " + DoubleToString(longAvgPrice, Digits);
|
|
msg = msg + " | Shorts: " + IntegerToString(shorts) + " @ " + DoubleToString(shortAvgPrice, Digits);
|
|
msg = msg + " | Equity: " + DoubleToString(AccountEquity(), 2);
|
|
|
|
// Use native MT5 notification instead of email
|
|
SendNotification(msg);
|
|
Print(msg);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void Log(string st)
|
|
{
|
|
if(DiagnosticModeOn)
|
|
if(logId>=0)
|
|
{
|
|
FileWrite(logId, TimeToStr(TimeCurrent(),TIME_DATE|TIME_SECONDS) + ": " + st);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CancelPendings(int op_type)
|
|
{
|
|
for(int cnt=OrdersTotal()-1; cnt>=0; cnt--)
|
|
{
|
|
OrderSelect(cnt, SELECT_BY_POS);
|
|
if(OrderMagicNumber()==MagicNum && OrderSymbol()==Symbol())
|
|
{
|
|
if((op_type==OP_BUY) && ((OrderType()==OP_BUYLIMIT)||(OrderType()==OP_BUYSTOP)))
|
|
{
|
|
OrderDelete(OrderTicket());
|
|
}
|
|
if((op_type==OP_SELL) && ((OrderType()==OP_SELLLIMIT)||(OrderType()==OP_SELLSTOP)))
|
|
{
|
|
OrderDelete(OrderTicket());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CloseAllTrades(int cmd)
|
|
{
|
|
for(int cnt=OrdersTotal()-1; cnt>=0; cnt--)
|
|
{
|
|
OrderSelect(cnt, SELECT_BY_POS);
|
|
if(OrderMagicNumber()==MagicNum && OrderType()==cmd)
|
|
// OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), slippage(), White);
|
|
MqlTradeResult result= {};
|
|
MqlTradeRequest request= {};
|
|
request.order=OrderTicket();
|
|
request.price=OrderClosePrice();
|
|
request.volume=OrderLots();
|
|
request.action=TRADE_ACTION_CLOSE_BY;
|
|
OrderSend(request,result);
|
|
//--- write the server reply to log
|
|
Print("Close result: ") ;
|
|
}
|
|
CancelPendings(cmd);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int CalcSpread()
|
|
{
|
|
//--- obtain spread from the symbol properties
|
|
bool spreadfloat=SymbolInfoInteger(Symbol(),SYMBOL_SPREAD_FLOAT);
|
|
string comm=StringFormat("Spread %s = %I64d points\r\n",
|
|
spreadfloat?"floating":"fixed",
|
|
SymbolInfoInteger(Symbol(),SYMBOL_SPREAD));
|
|
//--- now let's calculate the spread by ourselves
|
|
double ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
|
|
double bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);
|
|
double spread=ask-bid;
|
|
int spread_points=(int)MathRound(spread/SymbolInfoDouble(Symbol(),SYMBOL_POINT));
|
|
comm=comm+"Calculated spread = "+(string)spread_points+" points";
|
|
Comment(comm);
|
|
return spread_points;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int slippage()
|
|
{
|
|
return CalcSpread();
|
|
//return(MarketInfo(Symbol(), MODE_SPREAD));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int init()
|
|
{
|
|
double levels;
|
|
int cnt;
|
|
AboveHigh= false;
|
|
BelowLow= false;
|
|
bFirstTick= false;
|
|
bInit= false;
|
|
//int rc= IDYES;
|
|
double tmp;
|
|
|
|
int MaxProfit= 0;
|
|
// bConfirmed removed - always confirmed
|
|
int MargReq;
|
|
|
|
|
|
|
|
bValidSettings= false;
|
|
if(Lots<MarketInfo(Symbol(), MODE_MINLOT))
|
|
{
|
|
errMsg= "Illegal lot amount!";
|
|
//Alert(errMsg);
|
|
return(0);
|
|
}
|
|
if(Entry<MarketInfo(Symbol(), MODE_STOPLEVEL)*Point && Entry>0)
|
|
{
|
|
errMsg= "Illegal Entry!";
|
|
//Alert(errMsg);
|
|
return(0);
|
|
}
|
|
if(TP<MarketInfo(Symbol(), MODE_STOPLEVEL)*Point && TP>0)
|
|
{
|
|
errMsg= "Illegal TakeProfitShort!";
|
|
//Alert(errMsg);
|
|
return(0);
|
|
}
|
|
if(StopLoss<MarketInfo(Symbol(), MODE_STOPLEVEL) && StopLoss>0)
|
|
{
|
|
errMsg= "Illegal StopLoss!";
|
|
//Alert(errMsg);
|
|
return(0);
|
|
}
|
|
|
|
bValidSettings= true;
|
|
|
|
// License check removed - web.mq5 no longer used
|
|
bool bAccess = true; // Always allow access
|
|
bGetOutHandled= false;
|
|
if(DiagnosticModeOn)
|
|
logId= FileOpen(WindowExpertName()+MagicNum+"_"+TimeCurrent()+".log",FILE_WRITE);
|
|
Log("Version="+VERSION);
|
|
initialCycleEquity= BaseEquity;
|
|
tickValue= MarketInfo(Symbol(), MODE_TICKVALUE);
|
|
Log("Master="+Master+",Restart="+Restart);
|
|
|
|
if(TP==0)
|
|
TakeProfit= MathPow(10, Digits)*(Entry+Point/2);
|
|
else
|
|
TakeProfit= MathPow(10, Digits)*(TP+Point/2);
|
|
Print("TakeProfit="+TakeProfit);
|
|
levels= (HIGH-LOW)/Entry;
|
|
MaxProfit= TakeProfit*tickValue*Lots*levels;
|
|
Log("Digits="+Digits+",Bid="+Bid+",MODE_MARGINREQUIRED="+MarketInfo(Symbol(), MODE_MARGINREQUIRED)+",MODE_MARGINCALCMODE="+MarketInfo(Symbol(), MODE_MARGINCALCMODE));
|
|
Print("MODE_TICKVALUE="+MarketInfo(Symbol(),MODE_TICKVALUE));
|
|
if(MarketInfo(Symbol(), MODE_MARGINCALCMODE)==0)
|
|
{
|
|
MargReq= Lots*MarketInfo(Symbol(), MODE_MARGINREQUIRED);
|
|
}
|
|
else
|
|
MargReq= Lots*(levels+1)*(((HIGH-LOW)/2)+LOW)*MarketInfo(Symbol(), MODE_MARGINREQUIRED)/Bid;
|
|
Print("MargReq="+MargReq);
|
|
Log("levels="+levels+",Entry="+Entry);
|
|
levels= levels*Entry*(levels+1); //The maximal loss in points sum=n*(a1+an)/2
|
|
Log("levels="+levels+",tickValue="+tickValue+",Lots="+Lots);
|
|
MaximalLoss= (levels/Point)*tickValue*Lots/2;
|
|
|
|
if(!IsOptimization())
|
|
{
|
|
//newParamString= HIGH+","+LOW+","+Entry+","+Lots;
|
|
bool bSame= false;
|
|
|
|
if(GlobalVariableCheck("initialCycleEquity_"+MagicNum))
|
|
{
|
|
initialCycleEquity= GlobalVariableGet("initialCycleEquity_"+MagicNum);
|
|
Log("initialCycleEquity loaded: " + initialCycleEquity);
|
|
}
|
|
|
|
if(GlobalVariableCheck("High_"+MagicNum))
|
|
if(GlobalVariableCheck("Low_"+MagicNum))
|
|
if(GlobalVariableCheck("Entry_"+MagicNum))
|
|
if(GlobalVariableCheck("Lots_"+MagicNum))
|
|
{
|
|
if(GlobalVariableGet("High_"+MagicNum)==HIGH)
|
|
if(GlobalVariableGet("Low_"+MagicNum)==LOW)
|
|
if(GlobalVariableGet("Entry_"+MagicNum)==Entry)
|
|
if(GlobalVariableGet("Lots_"+MagicNum)==Lots)
|
|
bSame= true;
|
|
Log("Values: "+bSame);
|
|
Log(GlobalVariableGet("High_"+MagicNum)+","+HIGH);
|
|
Log(GlobalVariableGet("Low_"+MagicNum)+","+LOW);
|
|
Log(GlobalVariableGet("Entry_"+MagicNum)+","+Entry);
|
|
Log(GlobalVariableGet("Lots_"+MagicNum)+","+Lots);
|
|
}
|
|
|
|
if(!bSame)
|
|
{
|
|
int MinReq= MaximalLoss+MargReq-MaxProfit;
|
|
|
|
|
|
|
|
|
|
// Replaced MessageBox with Print - check logs for margin requirements
|
|
Print("MARGIN INFO - Total Margin Required: ("+MargReq+")"+
|
|
" Max Potential Loss: ("+MaximalLoss + ")"+
|
|
" Max Potential Profit: " + MaxProfit+
|
|
" Minimum Funds Required: "+MinReq);
|
|
//Log("Msgbox: "+MaximalLoss+",rc="+rc);
|
|
// if(rc==IDYES)
|
|
// {
|
|
GlobalVariableSet("High_"+MagicNum, HIGH);
|
|
GlobalVariableSet("Low_"+MagicNum, LOW);
|
|
GlobalVariableSet("Entry_"+MagicNum, Entry);
|
|
GlobalVariableSet("Lots_"+MagicNum, Lots);
|
|
Log("Vars saved");
|
|
// }
|
|
}
|
|
}
|
|
|
|
closeOnProfit= TakeProfitLevelPercent*AccountEquity()/100;
|
|
initEquity= BaseEquity; //AccountEquity();
|
|
if(GlobalVariableCheck(MagicNum+"_withdraw"))
|
|
{
|
|
tmp= GlobalVariableGet(MagicNum+"_withdraw");
|
|
if(tmp==0)
|
|
bWithdrawMailSent= false;
|
|
else
|
|
bWithdrawMailSent= true;
|
|
}
|
|
|
|
//if(IDYES==rc)
|
|
// {
|
|
for(int i=0; i<MAX_TRADES; i++)
|
|
{
|
|
longsTicket[i]= -1;
|
|
shortsTicket[i]= -1;
|
|
}
|
|
stoplevel= MarketInfo(Symbol(), MODE_STOPLEVEL);
|
|
|
|
|
|
Log("Currency: " + Symbol() + ",Period: " + Period());
|
|
for(cnt=0; cnt<OrdersTotal(); cnt++)
|
|
{
|
|
if(OrderSelect(cnt, SELECT_BY_POS))
|
|
if(OrderMagicNumber()==MagicNum && lastTicketSentOpen<OrderTicket() && ((OrderType()==OP_BUY)||(OrderType()==OP_SELL)))
|
|
lastTicketSentOpen= OrderTicket();
|
|
}
|
|
for(cnt=0; cnt<OrdersHistoryTotal(); cnt++)
|
|
{
|
|
if(OrderSelect(cnt, SELECT_BY_POS, MODE_HISTORY))
|
|
if(OrderMagicNumber()==MagicNum && lastTicketSentClose<OrderTicket() && ((OrderType()==OP_BUY)||(OrderType()==OP_SELL)))
|
|
lastTicketSentClose= OrderTicket();
|
|
}
|
|
|
|
bEnableLongs= (OpenNewTrades=="Y") || (OpenNewTrades=="y") || (OpenNewTrades=="L") || (OpenNewTrades=="l");
|
|
bEnableShorts= (OpenNewTrades=="Y") || (OpenNewTrades=="y") || (OpenNewTrades=="S") || (OpenNewTrades=="s");
|
|
if(!bEnableLongs)
|
|
CancelPendings(OP_BUY);
|
|
if(!bEnableShorts)
|
|
CancelPendings(OP_SELL);
|
|
|
|
Log("bEnableShorts="+bEnableShorts+",bEnableLongs="+bEnableLongs);
|
|
|
|
bOpposite= Opposite;
|
|
|
|
Log("slippage="+slippage()+",bFirstTick="+bFirstTick);
|
|
for(cnt=0; cnt<MAX_LOG_TRADES; cnt++)
|
|
logTickets[cnt]= -1;
|
|
logTicketsCounter= 0;
|
|
|
|
bInit= true;
|
|
|
|
|
|
bGetOutOK= (GetOut=="L") || (GetOut=="A") || (GetOut=="l") || (GetOut=="a") || (GetOut=="S" || GetOut=="s" || GetOut=="N" || GetOut=="n" || GetOut=="X" || GetOut=="x");
|
|
bOpenNewTradesOK= (OpenNewTrades=="Y") || (OpenNewTrades=="y") || (OpenNewTrades=="L") || (OpenNewTrades=="l") ||
|
|
(OpenNewTrades=="N") || (OpenNewTrades=="n") || (OpenNewTrades=="S") || (OpenNewTrades=="s");
|
|
|
|
double l= MarketInfo(Symbol(),MODE_MINLOT);
|
|
lotDigits= 0;
|
|
while(l<1)
|
|
{
|
|
l=l*10;
|
|
lotDigits++;
|
|
}
|
|
Log("HIGH= "+HIGH+",LOW= "+LOW+",Entry="+Entry+",TRADE_RANGE="+TRADE_RANGE+",initEquity="+initEquity+",lotDigits="+lotDigits);
|
|
|
|
return(0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
int deinit()
|
|
{
|
|
double tmp= 0;
|
|
if(ObjectFind(MagicNum+"_notActive1")!=-1)
|
|
ObjectDelete(MagicNum+"_notActive1");
|
|
|
|
if(ObjectFind(MagicNum+"_notActive2")!=-1)
|
|
ObjectDelete(MagicNum+"_notActive2");
|
|
|
|
if(bAccess)
|
|
{
|
|
if(logTicketsCounter>0)
|
|
{
|
|
tradeLogId= FileOpen("TradesLog_"+TimeToStr(TimeCurrent(),TIME_DATE | TIME_MINUTES)+".txt", FILE_WRITE);
|
|
for(int i=0; i<logTicketsCounter; i++)
|
|
{
|
|
if(OrderSelect(logTickets[i], SELECT_BY_TICKET))
|
|
if(!(OrderCloseTime()!=0 && OrderClosePrice()==OrderTakeProfit()))
|
|
{
|
|
FileWrite(tradeLogId, "Order ticket " + logTickets[i] + " should have been closed at " + TimeToStr(logTicketsTime[logTicketsCounter], TIME_DATE | TIME_MINUTES));
|
|
}
|
|
}
|
|
FileClose(tradeLogId);
|
|
}
|
|
if(bWithdrawMailSent)
|
|
tmp= 1;
|
|
GlobalVariableSet(MagicNum+"_withdraw", tmp);
|
|
Log("uninit reason="+UninitializeReason());
|
|
|
|
GlobalVariableSet("initialCycleEquity_"+MagicNum, initialCycleEquity);
|
|
|
|
// if the EA is detached, del the parameters file.
|
|
if(/*UninitializeReason()==REASON_CHARTCLOSE ||*/ UninitializeReason()==REASON_REMOVE)
|
|
{
|
|
Log("del globals");
|
|
GlobalVariableDel("High_"+MagicNum);
|
|
GlobalVariableDel("Low_"+MagicNum);
|
|
GlobalVariableDel("Entry_"+MagicNum);
|
|
GlobalVariableDel("Lots_"+MagicNum);
|
|
GlobalVariableDel("initialCycleEquity_"+MagicNum);
|
|
}
|
|
}
|
|
|
|
if(-1!=ObjectFind(MagicNum+"_status"))
|
|
ObjectDelete(MagicNum+"_status");
|
|
|
|
|
|
if(-1!=ObjectFind(MagicNum+"_status11"))
|
|
ObjectDelete(MagicNum+"_status11");
|
|
|
|
//RemoveEAStatusLabel(MagicNum);
|
|
|
|
if(DiagnosticModeOn)
|
|
FileClose(logId);
|
|
return(0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int CreateLongTrade(double tradePrice, double lots)
|
|
{
|
|
int rc= -1;
|
|
int cmd= -1;
|
|
double price;
|
|
double sl= 0;
|
|
double tp= 0;
|
|
|
|
if(MathAbs(tradePrice-Bid)>=TRADE_RANGE*Point)
|
|
{
|
|
Print("CreateLongTrade failed. tradePrice="+tradePrice+",Bid="+Bid+",TRADE_RANGE="+TRADE_RANGE+",Point="+Point);
|
|
Log("CreateLongTrade failed. tradePrice="+tradePrice+",Bid="+Bid+",TRADE_RANGE="+TRADE_RANGE+",Point="+Point);
|
|
return(rc);
|
|
}
|
|
|
|
if((tradePrice<=LongLimit)|| LongLimit==0)
|
|
if(bEnableLongs)
|
|
{
|
|
if(tradePrice==Bid)
|
|
{
|
|
cmd= OP_BUY;
|
|
price= Ask;
|
|
}
|
|
else
|
|
if(tradePrice<=Bid-stoplevel*Point)
|
|
{
|
|
cmd= OP_BUYLIMIT;
|
|
price= tradePrice+slippage()*Point;
|
|
}
|
|
else
|
|
if(tradePrice>=Bid+stoplevel*Point)
|
|
{
|
|
cmd= OP_BUYSTOP;
|
|
price= tradePrice+slippage()*Point;
|
|
}
|
|
else
|
|
{
|
|
Print("CreateLongTrade ERROR tradePrice="+tradePrice+",Bid="+Bid);
|
|
Log("CreateLongTrade ERROR tradePrice="+tradePrice+",Bid="+Bid);
|
|
}
|
|
|
|
if(cmd!=-1)
|
|
{
|
|
if(TakeProfit>0)
|
|
tp= price+TakeProfit*Point;
|
|
if(StopLoss>0)
|
|
sl= price-StopLoss*Point;
|
|
|
|
if(isOkToBUY(OrdersTotal(), price))
|
|
{
|
|
rc= OrderSend(Symbol(),cmd,lots,price,slippage(),sl,tp,WindowExpertName()+MagicNum,MagicNum,0,Blue);
|
|
//Sleep(3000);//sleep 3 seconds
|
|
if(-1==rc)
|
|
{
|
|
Log("Error= "+ GetLastError() + ", price="+price+",sl="+sl+",tp="+tp+",cmd="+cmd+",lots="+lots+",Bid="+Bid);
|
|
Print("error>> " + GetLastError());
|
|
//Alert("error>> " + GetLastError());
|
|
}
|
|
else
|
|
{
|
|
Log("LONG ticket=" + rc +",price="+price+",sl="+sl+",tp="+tp+",cmd="+cmd+",tradePrice="+tradePrice+",Bid="+Bid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int CreateShortTrade(double tradePrice, double lots)
|
|
{
|
|
int rc= -1;
|
|
int cmd= -1;
|
|
double price;
|
|
double sl= 0;
|
|
double tp= 0;
|
|
|
|
if(MathAbs(tradePrice-Bid)>=TRADE_RANGE*Point)
|
|
{
|
|
Log("CreateShortTrade failed. tradePrice="+tradePrice+",Bid="+Bid+",TRADE_RANGE="+TRADE_RANGE+",Point="+Point);
|
|
return(rc);
|
|
}
|
|
|
|
if(tradePrice>=ShortLimit)
|
|
if(bEnableShorts)
|
|
{
|
|
if(tradePrice==Bid)
|
|
{
|
|
cmd= OP_SELL;
|
|
price= Bid;
|
|
}
|
|
else
|
|
if(tradePrice>=Bid+stoplevel*Point)
|
|
{
|
|
cmd= OP_SELLLIMIT;
|
|
price= tradePrice;
|
|
}
|
|
else
|
|
if(tradePrice<=Bid-stoplevel*Point)
|
|
{
|
|
cmd= OP_SELLSTOP;
|
|
price= tradePrice;
|
|
}
|
|
else
|
|
Log("CreateShortTrade ERROR tradePrice="+tradePrice+",Bid="+Bid);
|
|
|
|
if(cmd!=-1)
|
|
{
|
|
if(TakeProfit>0)
|
|
tp= price-TakeProfit*Point;
|
|
if(StopLoss>0)
|
|
sl= price+StopLoss*Point;
|
|
|
|
if(isOkToSELL(OrdersTotal(), price))
|
|
{
|
|
rc= OrderSend(Symbol(),cmd,lots,price,slippage(),sl,tp,WindowExpertName()+MagicNum,MagicNum,0,Red);
|
|
|
|
//Sleep(3000);//sleep 3 seconds
|
|
if(-1==rc)
|
|
{
|
|
Log("SHORT Error= "+ GetLastError() + ", price="+price+",sl="+sl+",tp="+tp+",cmd="+cmd+",lots="+lots+",Bid="+Bid);
|
|
Print("error>> " + GetLastError());
|
|
//Alert("error>> " + GetLastError());
|
|
}
|
|
else
|
|
Log("SHORT ticket="+rc+",price="+price+",sl="+sl+",tp="+tp+",cmd="+cmd+",Bid="+Bid);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool IsPricesEqual(double price1, double price2)
|
|
{
|
|
int intPrice1= MathPow(10, Digits)*(price1+Point/2);
|
|
int intPrice2= MathPow(10, Digits)*(price2+Point/2);
|
|
//Log("intPrice1="+intPrice1+",intPrice2="+intPrice2);
|
|
return(intPrice1==intPrice2);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void RestoreTrades()
|
|
{
|
|
double tradePrice;
|
|
int idx= 0;
|
|
|
|
for(tradePrice= LOW; tradePrice<=HIGH; tradePrice+= Entry, idx++)
|
|
{
|
|
for(int cnt=0; cnt<OrdersTotal(); cnt++)
|
|
{
|
|
if(OrderSelect(cnt, SELECT_BY_POS))
|
|
if(OrderMagicNumber()==MagicNum)
|
|
{
|
|
Log("Ticket # " + OrderTicket() + " found type="+OrderType()+" Orderopenprice="+OrderOpenPrice()+" tradePrice="+tradePrice);
|
|
if(OrderType()==OP_SELL || OrderType()==OP_SELLLIMIT || OrderType()==OP_SELLSTOP)
|
|
{
|
|
if(IsPricesEqual(OrderOpenPrice(),tradePrice))
|
|
{
|
|
Log("Short ticket found. ticket=" + OrderTicket() + ",idx="+idx);
|
|
shortsTicket[idx]= OrderTicket();
|
|
}
|
|
}
|
|
else
|
|
if(OrderType()==OP_BUY || OrderType()==OP_BUYLIMIT || OrderType()==OP_BUYSTOP)
|
|
{
|
|
if(MathAbs(OrderOpenPrice()-tradePrice)<Entry/2)
|
|
{
|
|
Log("Long ticket found. ticket=" + OrderTicket() + ",idx="+idx);
|
|
longsTicket[idx]= OrderTicket();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Levels= idx;
|
|
Log("Levels= "+Levels);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CreateAllOrders()
|
|
{
|
|
double tradePrice;
|
|
int idx= 0;
|
|
int cnt;
|
|
|
|
Print("CreateAllOrders");
|
|
Log("CreateAllOrders");
|
|
RestoreTrades();
|
|
if(bOpposite)
|
|
{
|
|
if(HandleOpposite())
|
|
bOpposite= false;
|
|
}
|
|
for(idx= 0; idx<Levels; idx++)
|
|
{
|
|
tradePrice= LOW+idx*Entry;
|
|
if(longsTicket[idx]==-1)
|
|
{
|
|
longsTicket[idx]= CreateLongTrade(tradePrice, CalcLots());
|
|
Log("Open long,idx="+idx);
|
|
}
|
|
|
|
if(shortsTicket[idx]==-1)
|
|
{
|
|
shortsTicket[idx]= CreateShortTrade(tradePrice, CalcLots());
|
|
Log("Open short,idx="+idx);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
string GetOpenTradeString()
|
|
{
|
|
return(Symbol() + " OPEN:" + DoubleToStr(OrderLots(),2) + " @ " + DoubleToStr(OrderOpenPrice(),Digits) + " TP " + DoubleToStr(OrderTakeProfit(),Digits) + " SL " + DoubleToStr(OrderStopLoss(),Digits));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
string GetCloseTradeString()
|
|
{
|
|
return(Symbol() + " CLOSE:" + DoubleToStr(OrderLots(),2) + " @ " + DoubleToStr(OrderClosePrice(),Digits) + " TP " + DoubleToStr(OrderTakeProfit(),Digits) + " SL " + DoubleToStr(OrderStopLoss(),Digits));
|
|
}
|
|
/*
|
|
This functions scans the ticket arrays, and marks the closed trades.
|
|
Returns a true value if there is an entry with the value of -1.
|
|
*/
|
|
bool ScanAllOrders()
|
|
{
|
|
string st= "";
|
|
double spread = MarketInfo(Symbol(), MODE_SPREAD);
|
|
for(int i=0; i<Levels; i++)
|
|
{
|
|
if(-1!=longsTicket[i])
|
|
if(OrderSelect(longsTicket[i], SELECT_BY_TICKET))
|
|
{
|
|
if(0!=OrderCloseTime()) //order is closed
|
|
{
|
|
Log("Found a closed order i="+i);
|
|
spread = MarketInfo(Symbol(), MODE_SPREAD);
|
|
if(lastTicketSentClose<longsTicket[i] && lastTicketSentClose<(longsTicket[i]+spread) && lastTicketSentClose<(longsTicket[i]-spread))
|
|
{
|
|
lastTicketSentClose= longsTicket[i];
|
|
st= st+GetCloseTradeString()+"\n";
|
|
}
|
|
longsTicket[i]= -1;
|
|
Log("long idx " + i + " reset");
|
|
}
|
|
}
|
|
if(-1==longsTicket[i])
|
|
{
|
|
///scan for existing orders
|
|
longsTicket[i]= CreateLongTrade(LOW+i*Entry, CalcLots());
|
|
if(longsTicket[i]!=-1)
|
|
Log("long idx="+i+",ticket="+longsTicket[i]);
|
|
}
|
|
|
|
if(-1!=shortsTicket[i])
|
|
if(OrderSelect(shortsTicket[i], SELECT_BY_TICKET))
|
|
{
|
|
if(0!=OrderCloseTime() && OrderProfit()>0) //order is closed
|
|
{
|
|
spread = MarketInfo(Symbol(), MODE_SPREAD);
|
|
if(lastTicketSentClose<shortsTicket[i] && lastTicketSentClose<(shortsTicket[i]+spread) && lastTicketSentClose<(shortsTicket[i]-spread))
|
|
{
|
|
lastTicketSentClose= shortsTicket[i];
|
|
st= st+GetCloseTradeString()+"\n";
|
|
}
|
|
shortsTicket[i]= -1;
|
|
Log("short idx " + i + " reset");
|
|
}
|
|
}
|
|
if(-1==shortsTicket[i])
|
|
{
|
|
shortsTicket[i]= CreateShortTrade(LOW+i*Entry, CalcLots());
|
|
if(-1!=shortsTicket[i])
|
|
Log("short idx="+i+",ticket="+shortsTicket[i]);
|
|
}
|
|
}
|
|
if(st!="")
|
|
SendNotificationEx(Symbol() + " Position Closed",st);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void CalcAvgPrice()
|
|
{
|
|
|
|
longAvgPrice= 0;
|
|
longAvgLots= 0;
|
|
shortAvgPrice= 0;
|
|
shortAvgLots= 0;
|
|
longs= 0;
|
|
shorts= 0;
|
|
|
|
for(int i=0; i<OrdersTotal(); i++)
|
|
{
|
|
OrderSelect(i, SELECT_BY_POS);
|
|
if(OrderMagicNumber()==MagicNum && OrderSymbol()==Symbol())
|
|
{
|
|
if(OrderType()==OP_BUY)
|
|
{
|
|
longAvgPrice+= OrderOpenPrice()*OrderLots();
|
|
longAvgLots+= OrderLots();
|
|
longs++;
|
|
if(Bid==OrderTakeProfit())
|
|
AddTradeToLog(OrderTicket());
|
|
}
|
|
else
|
|
if(OrderType()==OP_SELL)
|
|
{
|
|
shortAvgPrice+= OrderOpenPrice()*OrderLots();
|
|
shortAvgLots+= OrderLots();
|
|
shorts++;
|
|
if(Ask==OrderTakeProfit())
|
|
AddTradeToLog(OrderTicket());
|
|
}
|
|
}
|
|
}
|
|
if(longAvgLots>0)
|
|
longAvgPrice= (longAvgPrice/longAvgLots);
|
|
if(shortAvgLots>0)
|
|
shortAvgPrice= shortAvgPrice/shortAvgLots;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
double CalcProfit(int MagicNumber)
|
|
{
|
|
int cnt;
|
|
double sum;
|
|
|
|
longProfit= 0;
|
|
shortProfit= 0;
|
|
string updateSt= "";
|
|
bool bUpdate;
|
|
int ticket= lastTicketSentOpen;
|
|
|
|
for(cnt=0; cnt<OrdersTotal(); cnt++)
|
|
{
|
|
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
|
|
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
|
|
{
|
|
bUpdate= false;
|
|
if(OrderType()==OP_BUY)
|
|
{
|
|
longProfit+= OrderProfit()+OrderSwap();
|
|
bUpdate= true;
|
|
}
|
|
else
|
|
if(OrderType()==OP_SELL)
|
|
{
|
|
shortProfit+= OrderProfit()+OrderSwap();
|
|
bUpdate= true;
|
|
}
|
|
if(bUpdate)
|
|
{
|
|
if(lastTicketSentOpen<OrderTicket())
|
|
lastTicketSentOpen= OrderTicket();
|
|
if(ticket<OrderTicket())
|
|
updateSt= updateSt+GetOpenTradeString()+"\n";
|
|
}
|
|
}
|
|
}
|
|
if(updateSt!="")
|
|
SendNotificationEx(Symbol() + " Position Opened", updateSt);
|
|
return(shortProfit+longProfit);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void HandleGetOut(bool bInit)
|
|
{
|
|
bool getOutLongs= ((GetOut=="L") || (GetOut=="A") || (GetOut=="l") || (GetOut=="a") || GetOut=="X" || GetOut=="x");
|
|
bool getOutShorts= (GetOut=="S" || GetOut=="s" || GetOut=="A" || GetOut=="a" || GetOut=="X" || GetOut=="x");
|
|
if(bInit)
|
|
{
|
|
for(int cnt= OrdersTotal()-1; cnt>=0; cnt--)
|
|
{
|
|
OrderSelect(cnt, SELECT_BY_POS);
|
|
if(OrderMagicNumber()==MagicNum && OrderSymbol()==Symbol())
|
|
{
|
|
if((OrderType()==OP_BUY && getOutLongs && (OrderProfit()>0 || GetOut=="X" || GetOut=="x")) ||
|
|
(OrderType()==OP_SELL && getOutShorts && (OrderProfit()>0 || GetOut=="X" || GetOut=="x")))
|
|
OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), MarketInfo(Symbol(),MODE_SPREAD), Purple);
|
|
if((GetOut=="X" || GetOut=="x") && OrderType()!=OP_BUY && OrderType()!=OP_SELL)
|
|
OrderDelete(OrderTicket());
|
|
}
|
|
}
|
|
}
|
|
|
|
if(GetOut!="N")
|
|
CalcProfit(MagicNum);
|
|
|
|
if(getOutLongs)
|
|
{
|
|
if(longProfit>=0)
|
|
CloseAllTrades(OP_BUY);
|
|
}
|
|
else
|
|
if(getOutShorts)
|
|
{
|
|
if(shortProfit>=0)
|
|
CloseAllTrades(OP_SELL);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool HandleOpposite()
|
|
{
|
|
int idx=-1;
|
|
int interval= Entry*MathPow(10,Digits);
|
|
double price;
|
|
double lots;
|
|
int s=0, l=0;
|
|
bool rc= true;
|
|
|
|
Log("Levels= "+Levels);
|
|
for(int i=0; i<Levels; i++)
|
|
{
|
|
if(shortsTicket[i]!=-1)
|
|
{
|
|
if(OrderSelect(shortsTicket[i], SELECT_BY_TICKET))
|
|
{
|
|
if(OrderType()==OP_SELL)
|
|
{
|
|
s++;
|
|
idx= i;
|
|
}
|
|
}
|
|
else
|
|
Log("Error select "+shortsTicket[i]);
|
|
}
|
|
if(longsTicket[i]!=-1)
|
|
{
|
|
if(OrderSelect(longsTicket[i], SELECT_BY_TICKET))
|
|
{
|
|
if(OrderType()==OP_BUY)
|
|
{
|
|
l++;
|
|
if(idx==-1)
|
|
idx= i;
|
|
}
|
|
}
|
|
else
|
|
Log("Error select " + longsTicket[i]);
|
|
}
|
|
}
|
|
Log("Longs="+l+",Short="+s);
|
|
if((l==0) && (s>0))
|
|
{
|
|
if(idx<(Levels-1))
|
|
{
|
|
if(-1!=longsTicket[idx+1])
|
|
{
|
|
if(OrderSelect(longsTicket[idx+1], SELECT_BY_TICKET))
|
|
rc= OrderDelete(OrderTicket());
|
|
}
|
|
if(rc)
|
|
{
|
|
lots= s*Lots;
|
|
price= LOW+(idx+1)*interval*Point;
|
|
CreateLongTrade(price, lots);
|
|
Log("Opposite long lots="+lots+",price="+price);
|
|
}
|
|
else
|
|
Log("Cannot delete ticket #"+OrderTicket());
|
|
}
|
|
else
|
|
Log("[ERR] Cannot set opposite long order, out of bounderies idx="+idx);
|
|
}
|
|
|
|
if((s==0)&&(l>0))
|
|
{
|
|
if(idx>0)
|
|
{
|
|
if(-1!=shortsTicket[idx-1])
|
|
{
|
|
if(OrderSelect(shortsTicket[idx-1], SELECT_BY_TICKET))
|
|
rc= OrderDelete(OrderTicket());
|
|
}
|
|
if(rc)
|
|
{
|
|
lots= l*Lots;
|
|
price= LOW+(idx-1)*interval*Point;
|
|
CreateShortTrade(price, lots);
|
|
Log("Opposite short lots="+lots+",price="+price);
|
|
}
|
|
else
|
|
Log("Cannot delete ticket #"+OrderTicket());
|
|
}
|
|
else
|
|
Log("[ERR] Cannot set opposite short order, out of bounderies idx="+idx);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void GlobalCloseAllTrades()
|
|
{
|
|
Log("GlobalCloseAllTrades");
|
|
for(int cnt=OrdersTotal()-1; cnt>=0; cnt--)
|
|
if(OrderSelect(cnt, SELECT_BY_POS))
|
|
{
|
|
if(OrderType()==OP_BUY || OrderType()==OP_SELL)
|
|
OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), MarketInfo(Symbol(), MODE_SPREAD), White);
|
|
else
|
|
OrderDelete(OrderTicket());
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void SendEmailToBroker(int profit)
|
|
{
|
|
string st= "";
|
|
st= "Hello,\n"+AccountName()+" here, Trading A/c " + AccountNumber() + ".\n";
|
|
st=st+"Would you kindly transfer $" + profit + " to my a/c # " + HoldingAccount + " as soon as possible?\n\n";
|
|
st=st+"Many thanks!\n\nRegards\n\n"+AccountName();
|
|
Print("Transfer Funds Request: " + st);
|
|
SendNotification("Transfer Funds Request: " + st);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int start()
|
|
{
|
|
string breakevenString;
|
|
string stRange= "";
|
|
int idx= 0;
|
|
int interval= Entry*MathPow(10,Digits);
|
|
double profit= CalcProfit(MagicNum);
|
|
static datetime lastPingTime= 0;
|
|
|
|
|
|
//Report.php handle
|
|
if((TimeCurrent()-lastPingTime)>=PingTimeMinutes*60)
|
|
{
|
|
string answer= "0";
|
|
if(IsDemo())
|
|
{
|
|
|
|
Print("http://letyourcomputertrade.com/php/report.php?email="+Email+"&Dacc="+AccountNumber()+"&bal="+AccountBalance()+"&equity="+AccountEquity());
|
|
|
|
if(GrabWeb("http://letyourcomputertrade.com/php/report.php?email="+Email+"&Dacc="+AccountNumber()+"&bal="+AccountBalance()+"&equity="+AccountEquity(), answer))
|
|
{ lastPingTime= TimeCurrent(); }
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
Print("http://letyourcomputertrade.com/php/report.php?email="+Email+"&Dacc="+AccountNumber()+"&bal="+AccountBalance()+"&equity="+AccountEquity());
|
|
if(GrabWeb("http://letyourcomputertrade.com/php/report.php?email="+Email+"&Lacc="+AccountNumber()+"&bal="+AccountBalance()+"&equity="+AccountEquity(), answer))
|
|
{
|
|
lastPingTime= TimeCurrent();
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle tp=0
|
|
for(int i=0; i<OrdersTotal(); i++)
|
|
if(OrderSelect(i, SELECT_BY_POS))
|
|
if(OrderMagicNumber()==MagicNum)
|
|
if(OrderTakeProfit()==0)
|
|
{
|
|
bool rc= false;
|
|
double tp;
|
|
if(OrderType()==OP_BUY)
|
|
tp= OrderOpenPrice()+TakeProfit*Point;
|
|
else
|
|
if(OrderType()==OP_SELL)
|
|
tp= OrderOpenPrice()-TakeProfit*Point;
|
|
else
|
|
continue;
|
|
|
|
if((tp<OrderClosePrice() && OrderType()==OP_BUY) || (tp>OrderClosePrice() && OrderType()==OP_SELL))
|
|
{
|
|
rc= OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), MarketInfo(Symbol(), MODE_SPREAD), White);
|
|
Log("Close Ticket #"+OrderTicket()+" modified tp to " + tp+ " res="+rc+",err="+GetLastError());
|
|
}
|
|
else
|
|
{
|
|
rc= OrderModify(OrderTicket(), 0, OrderStopLoss(), tp, 0, White);
|
|
Log("Ticket #"+OrderTicket()+" modified tp to " + tp+ " res="+rc+",err="+GetLastError());
|
|
}
|
|
}
|
|
|
|
double deltaToLong = LongLimit - (TRADE_RANGE/2);
|
|
double diffLongdelta = Ask - deltaToLong;
|
|
if(deltaToLong < Ask && diffLongdelta > moveRangeTrigger)
|
|
{
|
|
LongLimit = LongLimit - diffLongdelta;
|
|
|
|
}
|
|
|
|
double deltaToShort = ShortLimit + (TRADE_RANGE/2);
|
|
double diffShortdelta = deltaToShort - Bid;
|
|
if(deltaToShort > Bid && diffShortdelta > moveRangeTrigger)
|
|
{
|
|
ShortLimit = ShortLimit + diffLongdelta;
|
|
|
|
}
|
|
|
|
if(!bGetOutOK)
|
|
{
|
|
Comment("GetOut has an invalid value!");
|
|
Log("GetOut has an invalid value!");
|
|
return(0);
|
|
}
|
|
|
|
if(!bGetOutHandled)
|
|
{
|
|
bGetOutHandled= true;
|
|
HandleGetOut(true);
|
|
}
|
|
|
|
if(!bOpenNewTradesOK)
|
|
{
|
|
Comment("OpenNewTrades has an invalid value!");
|
|
Log("OpenNewTrades has an invalid value!");
|
|
return(0);
|
|
}
|
|
|
|
if(TakeProfitLevelPercent>0)
|
|
{
|
|
if(AccountEquity()>=(initialCycleEquity+closeOnProfit) || (AccountEquity() >= (TakeProfitLevelDollarAmount + initialCycleEquity)&& TakeProfitLevelDollarAmount >0))
|
|
{
|
|
bInit= false;
|
|
Log("TakeProfitLevel condition filled. Equity="+AccountEquity()+",profit="+profit);
|
|
if(Master)
|
|
{
|
|
GlobalCloseAllTrades();
|
|
//CloseAllTrades(OP_SELL);
|
|
//CloseAllTrades(OP_BUY);
|
|
if(!bWithdrawMailSent)
|
|
{
|
|
SendEmailToBroker(closeOnProfit);
|
|
bWithdrawMailSent= true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
bWithdrawMailSent= false;
|
|
}
|
|
|
|
if(!bInit)
|
|
{
|
|
Log("BInit=false");
|
|
int cnt= 0;
|
|
idx= 0;
|
|
for(cnt=0; cnt<OrdersTotal(); cnt++)
|
|
if(OrderSelect(cnt, SELECT_BY_POS))
|
|
if(OrderMagicNumber()==MagicNum)
|
|
idx++;
|
|
|
|
if(0==idx)
|
|
{
|
|
for(double tradePrice= LOW; tradePrice<=HIGH; tradePrice+= interval*Point, idx++)
|
|
{
|
|
longsTicket[idx]= -1;
|
|
shortsTicket[idx]= -1;
|
|
}
|
|
|
|
if(Restart)
|
|
{
|
|
initialCycleEquity= initialCycleEquity+closeOnProfit;
|
|
Log("Restarting.... AccountEquity="+initialCycleEquity);
|
|
bInit= true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(bInit)
|
|
{
|
|
if(!bFirstTick)
|
|
{
|
|
Log("First tick");
|
|
bFirstTick= true;
|
|
CreateAllOrders();
|
|
}
|
|
else
|
|
{
|
|
HandleGetOut(false);
|
|
ScanAllOrders();
|
|
}
|
|
CalcAvgPrice();
|
|
|
|
breakevenString= "Breakeven Longs="+DoubleToStr(longAvgPrice,Digits)+", Shorts="+DoubleToStr(shortAvgPrice,Digits);
|
|
Comment(breakevenString + "\n" + "Maximal loss: " + DoubleToStr(MaximalLoss,Digits) + "\nBase equity:"+ initialCycleEquity);
|
|
if(!BelowLow && Bid<LOW)
|
|
{
|
|
stRange= stRange + "\n" + "Price crossed LOW=" + DoubleToStr(LOW,Digits);
|
|
BelowLow= true;
|
|
}
|
|
if(!AboveHigh && Bid>HIGH)
|
|
{
|
|
stRange= stRange + "\n" + "Price crossed HIGH=" + DoubleToStr(HIGH,Digits);
|
|
AboveHigh= true;
|
|
}
|
|
if(stRange!="")
|
|
SendNotificationEx(Symbol() + " Range Exceeded", stRange);
|
|
}
|
|
else
|
|
Comment("The EA is not active");
|
|
return(0);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool isOkToSELL(int totOrds, double orderPrice)
|
|
{
|
|
bool doTrade = true;
|
|
bool isSellOpen = true;
|
|
for(int cnt=0; cnt<totOrds; cnt++)
|
|
{
|
|
|
|
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
|
|
if(OrderType()<=OP_SELLSTOP && // check for opened position
|
|
OrderSymbol()==Symbol()) // check for symbol
|
|
{
|
|
double dif = MathAbs(orderPrice - OrderClosePrice());
|
|
|
|
if(OrderType()==OP_SELL || OrderType()== OP_SELLLIMIT || OrderType()==OP_SELLSTOP) // go to short position
|
|
{
|
|
if(dif>Entry*Point)
|
|
isSellOpen = true;
|
|
else
|
|
{
|
|
isSellOpen = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
isSellOpen = CheckTradeContext();
|
|
doTrade = isSellOpen ;
|
|
|
|
return(doTrade);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool isOkToBUY(int totOrds, double orderPrice)
|
|
{
|
|
bool doTrade = true;
|
|
bool isBuyOpen = true;
|
|
for(int cnt=0; cnt<totOrds; cnt++)
|
|
{
|
|
|
|
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
|
|
if(OrderType()<=OP_SELLSTOP && // check for opened position
|
|
OrderSymbol()==Symbol()) // check for symbol
|
|
{
|
|
double dif = MathAbs(orderPrice - OrderClosePrice());
|
|
|
|
if(OrderType()==OP_BUY || OrderType()==OP_BUYLIMIT || OrderType()==OP_BUYSTOP) // go to long position
|
|
{
|
|
if(dif>Entry*Point)
|
|
isBuyOpen = true;
|
|
else
|
|
{
|
|
isBuyOpen = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
isBuyOpen = CheckTradeContext();
|
|
doTrade = isBuyOpen ;
|
|
|
|
|
|
|
|
return(doTrade);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CheckTradeContext()
|
|
{
|
|
|
|
|
|
// check whether the trade context is free
|
|
if(!IsTradeAllowed())
|
|
{
|
|
Print("Trade context is busy! Wait until it is free...");
|
|
// infinite loop
|
|
while(true)
|
|
{
|
|
// if the expert was stopped by the user, stop operation
|
|
if(IsStopped())
|
|
{
|
|
Print("The expert was stopped by the user!");
|
|
return(-1);
|
|
}
|
|
// if trade context has become free, terminate the loop and start trading
|
|
if(IsTradeAllowed())
|
|
{
|
|
Print("Trade context has become free!");
|
|
break;
|
|
}
|
|
// if no loop breaking condition has been met, "wait" for 0.1 sec
|
|
// and restart checking
|
|
Sleep(100);
|
|
}
|
|
}
|
|
|
|
return(true);
|
|
|
|
}
|
|
//+------------------------------------------------------------------+
|