Files
mql-trading-bots/OrdersEA (1).mq4
Garfield c342966488 Clean up OrdersEA MT4 version - Remove WinAPI and license dependencies
- Removed #include WinUser32.mqh (no more MessageBox)
- web.mq4 include already disabled, removed comment
- Replaced MessageBox with Print() for margin info
- Replaced SendMailEx with SendNotificationEx using native MT4 Alert()
- Updated copyright to Garfield Heron / fetcherpay.com
- Email default set to garfield@fetcherpay.com
2026-03-24 11:49:41 -04:00

1231 lines
36 KiB
Plaintext
Executable File

//+------------------------------------------------------------------+
//| OrdersEA.mq4 |
//| Copyright 2024, Garfield Heron |
//| https://fetcherpay.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Garfield Heron"
#property link "https://fetcherpay.com"
#define VERSION "Version 1.1 gh"
// WinAPI include removed - using native MT4 functions
// web.mq4 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_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 bAccess;
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++;
}
}
void SendNotificationEx(string title, string subject)
{
string st= subject;
if(!IsOptimization())
{
st= st + "Price now: " + DoubleToStr(Bid, Digits) + "\n";
st= st +"Longs: " + longs + " @ " + DoubleToStr(longAvgPrice, Digits) + "\n";
st= st +"Shorts: " + shorts + " @ " + DoubleToStr(shortAvgPrice, Digits) + "\n";
st= st +"Account Equity: + "+ AccountEquity() +"\n";
st= st +"Account Balance: + "+ AccountBalance() +"\n";
SendMail(title, st);
}
}
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);
}
CancelPendings(cmd);
}
int slippage()
{
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;
bAccess= true ;//IsOK(Email, MagicNum, VERSION );
//Alert(bAccess);
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;
MessageBox("Total Margin Required: ("+MargReq+")"+
"\nMax Potential Loss: ("+MaximalLoss + ")"+
"\nMax Potential Profit: " + MaxProfit+
"\n\nMinimum Funds Required: "+MinReq,"",MB_YESNO);
//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)
{
return 0;
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);
Alert("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 (false);
}
// 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);
}