//+------------------------------------------------------------------+ //| Pulse_EA_project_MT5.mq5 | //| Copyright 2024, MQL Development | //| https://www.mqldevelopment.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MQL Development" #property link "https://www.mqldevelopment.com/" #property version "1.00" #include CTrade trade; #define MaxOrders 10000 struct new_trade_store { int trade_ticket; int trade_type; int trade_magic_no; double trade_open_price; double trade_close_price; datetime trade_open_time; datetime trade_close_time; double trade_sl; double trade_tp; double trade_lot; double trade_profit; new_trade_store() { trade_ticket = -1; trade_type = -1; trade_magic_no = -1; trade_open_price = -1; trade_close_price = -1; trade_open_time = -1; trade_close_time = -1; trade_sl = -1; trade_tp = -1; trade_lot = -1; trade_profit = -1; } }; new_trade_store od[MaxOrders]; enum trade_typ { buy, // Buy reverse, // Reverse }; enum EA_TYPE { Tally_Sim, // Tally Sim Tally_Trade, // Tally Trade }; input string gnrlsettings = " ================ General Settings =================== ";//_ input EA_TYPE eaType = Tally_Sim; // EA Option input double tpPips = 20; // Tp Pips input double slPips = 20; // SL Pips input double lot = 0.1; // Lot Size input double glTp = 20; // Global TP input double glSl = 10; // Global SL input string gnrlesettings = " ================ Tally Sim Settings =================== ";//_ trade_typ ordTyp = buy; // Order Type (Tally Sim) input int magicNo = 123; // Magic # (Tally Sim) input string fileName = "TradeDataFile.csv"; // File Name (Tally Sim) input string grlesettings = " ================ Tally Trade Settings =================== ";//_ input trade_typ tradesDirection = buy; // Order Type (Tally Trade) input int magicNo1 = 1234; // Magic # (Tally Trade) input bool CopyTallyTrade = true; // Enable Copy Trade input string Settings5 = "------------- Time Filter Settings -------------"; //_ input bool enableTimeFilter = false; // Enable Time Filter input string startTime = "22:00"; // Start Time input string endTime = "01:00"; // End Time input bool useFridayClose = false; // Use Friday Close input string closeFriday = "23:00"; // Friday Close Time input bool useMondayOpen = false; // Use Monday Open input string mondayOpen = "01:00"; // Monday Open Time input string Settings25 = "------------- Daily Draw Limit Settings -------------"; //_ input bool UseDailyDrawdownLimit = true; // Enable Daily Draw Down input double DailyDrawdownAmount = 2000; // $2000 limit input string DrawdownResetTime = "05:00"; // Enable Trading At input string Settings6 = "------------- Display Settings -------------"; //_ input int tradeLineThickness = 2; // Trade Line Thickness input int dollarFontSize = 10; // Dollar Text Font Size input color dollarFontColor = clrAqua; // Dollar Text Font Colour input string horizontalLineName = "close"; // Horizontal Line Name input string indSettings = " ================ Indicator Settings =================== ";//_ input color Dot_Color = clrOrangeRed; input double StartingBalance = 10000; input string MagicNumbers = "123"; input int MA_Period = 5; input ENUM_MA_METHOD MA_Method = MODE_SMA; input string fileName1 = "TradeDataFile.csv"; // File Name bool tpSlHit = false; int ticketAssigner = 1; int handler; double bufferData[]; ushort u_sep; // The code of the separator character string sep = ":"; // A separator as a character string result1[]; datetime startTradingTime = 0, endTradingTime = 0, dailyDrawDownTime = 0; datetime mondayTradingStart = 0, fridayTradingClose = 0; datetime eaStartTime; // Store EA start time double g_dailyStartBalance; bool enableTradingDaily = true; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- tpSlHit = false; ticketAssigner = 1; if(eaType == Tally_Trade) { ArrayInitialize(bufferData,0.0); handler = iCustom(Symbol(),PERIOD_CURRENT,"Pulse Balance Indicator Sim",Dot_Color,StartingBalance,MagicNumbers,MA_Period,MA_Method,fileName1); ArraySetAsSeries(bufferData,true); } trade.SetExpertMagicNumber(magicNo1); trade.SetDeviationInPoints(10); trade.SetTypeFilling(ORDER_FILLING_IOC); trade.LogLevel(LOG_LEVEL_ALL); trade.SetAsyncMode(false); setStart_EndTime_modify(true,startTime,endTime,startTradingTime,endTradingTime); setStart_EndTime(true,startTime,endTime,startTradingTime,endTradingTime); g_dailyStartBalance = AccountInfoDouble(ACCOUNT_BALANCE); enableTradingDaily = true; eaStartTime = TimeCurrent(); // Track EA start time //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- timeConversion(); if(TimeCurrent() >= dailyDrawDownTime && enableTradingDaily == false) { enableTradingDaily = true; } markClosedOrder(eaStartTime); CheckVirtualGlobalTpSl(); checkTPSLHit(); newBar(); if(newDayBar()) { g_dailyStartBalance = AccountInfoDouble(ACCOUNT_BALANCE); } MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); bool doTrading = true; if(useMondayOpen) { if(dt.day_of_week == 1 && TimeCurrent() < mondayTradingStart) // it's Monday { doTrading = false; } } if(useFridayClose) { if(dt.day_of_week == 5 && TimeCurrent() >= fridayTradingClose) // it's Friday { doTrading = false; closeAllActiveOrders(); } } setStart_EndTime_modify(false,startTime,endTime,startTradingTime,endTradingTime); setStart_EndTime(false,startTime,endTime,startTradingTime,endTradingTime); if(enableTimeFilter && TimeCurrent() >= startTradingTime && TimeCurrent() < endTradingTime) { return; } placeTrade(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool newBar() { static datetime lastbar; datetime curbar = iTime(Symbol(), PERIOD_CURRENT, 0); if(lastbar != curbar) { lastbar = curbar; Print(" ---------------------- New Bar :: ---------------------- ",lastbar); return (true); } else { return (false); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool newDayBar() { static datetime lastbar1; datetime curbar1 = iTime(Symbol(), PERIOD_D1, 0); if(lastbar1 != curbar1) { lastbar1 = curbar1; Print(" ---------------------- New Day Bar :: ---------------------- ",lastbar1); return (true); } else { return (false); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void closeAllActiveOrders() { for(int i=PositionsTotal()-1; i >=0 ; i--) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC) == magicNo && PositionGetString(POSITION_SYMBOL) == Symbol()) { if(trade.PositionClose(ticket)) { Print("Closing All Active Orders"); Print("Position closed ", ticket); } else { Print("Cannot close order: ",GetLastError()); } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void timeConversion() { MqlDateTime date1, date_1,date_2; TimeToStruct(iTime(Symbol(),PERIOD_CURRENT,0),date1); u_sep=StringGetCharacter(sep,0); StringSplit(mondayOpen,u_sep,result1); date1.hour = (int)StringToInteger(result1[0]); date1.min = (int)StringToInteger(result1[1]); mondayTradingStart = StructToTime(date1); TimeToStruct(iTime(Symbol(),PERIOD_CURRENT,0),date_1); StringSplit(closeFriday,u_sep,result1); date_1.hour = (int)StringToInteger(result1[0]); date_1.min = (int)StringToInteger(result1[1]); fridayTradingClose = StructToTime(date_1); TimeToStruct(iTime(Symbol(),PERIOD_CURRENT,0),date_2); StringSplit(DrawdownResetTime,u_sep,result1); date_2.hour = (int)StringToInteger(result1[0]); date_2.min = (int)StringToInteger(result1[1]); dailyDrawDownTime = StructToTime(date_2); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void placeTrade() { if(tpSlHit == false) { if(ordTyp == buy) { placeBuyTrade(); } if(ordTyp == reverse) { placeSellTrade(); } tpSlHit = true; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void placeBuyTrade() { double buySl = 0,buyTp=0; double Ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK); if(slPips != 0) { buySl = Ask - (slPips * Point() * 10); } if(tpPips != 0) { buyTp = Ask + (tpPips * Point() * 10); } AddToStructure(ticketAssigner,0,magicNo,Ask,0,TimeCurrent(),0,buySl,buyTp,lot,0); ticketAssigner++; if(enableTradingDaily == true) { if(eaType == Tally_Trade && CopyTallyTrade) { if(CopyBuffer(handler, 0, 0, 4, bufferData) < 0) { Print("Error in copying Buffer data ", GetLastError()); } double balance = bufferData[1]; if(CopyBuffer(handler, 1, 0, 4, bufferData) < 0) { Print("Error in copying Buffer data ", GetLastError()); } double MA = bufferData[1]; Print(" Balance = ",balance," MA = ",MA); if(tradesDirection == buy) { if(balance > MA) { if(!trade.Buy(lot, Symbol(),SymbolInfoDouble(Symbol(),SYMBOL_ASK),buySl,buyTp,"Buy Trade")) { Print(" Error in Placing Buy Trade : ",GetLastError()); } } else { Print(" Trade is not Placed because Balance is less than MA Value "); } } else { if(balance < MA) { if(!trade.Sell(lot,Symbol(),SymbolInfoDouble(Symbol(),SYMBOL_BID),buyTp,buySl,"Sell Trade")) { Print(" Error in Placing Sell Trade : ",GetLastError()); } } else { Print(" Trade is not Placed because Balance is less than MA Value "); } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void placeSellTrade() { double sellSl = 0, sellTp = 0; double Bid = SymbolInfoDouble(Symbol(),SYMBOL_BID); if(slPips != 0) { sellSl = Bid + (slPips * 10 * Point()); } if(tpPips != 0) { sellTp = Bid - (tpPips * 10 * Point()); } AddToStructure(ticketAssigner,1,magicNo,Bid,0,TimeCurrent(),0,sellSl,sellTp,lot,0); ticketAssigner++; if(enableTradingDaily == true) { if(eaType == Tally_Trade && CopyTallyTrade) { if(CopyBuffer(handler, 0, 0, 4, bufferData) < 0) { Print("Error in copying Buffer data ", GetLastError()); } double balance = bufferData[1]; if(CopyBuffer(handler, 1, 0, 4, bufferData) < 0) { Print("Error in copying Buffer data ", GetLastError()); } double MA = bufferData[1]; Print(" Balance = ",balance," MA = ",MA); if(tradesDirection == reverse) { if(balance < MA) { if(!trade.Sell(lot,Symbol(),Bid,sellSl,sellTp,"Sell Trade")) { Print(" Error in Placing Sell Trade : ",GetLastError()); } } else { Print(" Trade is not Placed because Balance is less than MA Value "); } } else { if(balance > MA) { if(!trade.Buy(lot,Symbol(),SymbolInfoDouble(Symbol(),SYMBOL_ASK),sellTp,sellSl,"Buy Trade")) { Print(" Error in Placing Buy Trade : ",GetLastError()); } } else { Print(" Trade is not Placed because Balance is less than MA Value "); } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void AddToStructure(int ticket, int type, int magic, double open_price, double close_price, datetime open_time, datetime close_time, double sl, double tp, double lotSize, double profit) { for(int i = 0; i < MaxOrders; i++) { if(od[i].trade_ticket == -1) { od[i].trade_ticket = ticket; od[i].trade_type = type; od[i].trade_magic_no = magic; od[i].trade_open_price = open_price; od[i].trade_close_price = close_price; od[i].trade_open_time = open_time; od[i].trade_close_time = close_time; od[i].trade_sl = sl; od[i].trade_tp = tp; od[i].trade_lot = lotSize; od[i].trade_profit = profit; Print(" ========== Trade Placed of Ticket ========== ",ticket); Print("[AddToStructure] Added at index: ", i, " | Ticket = ", ticket, " | Type = ", type, " | Magic = ", magic, " | OpenPrice = ", open_price, " | ClosePrice = ", close_price, " | SL = ", sl, " | TP = ", tp, " | Lots = ", lotSize, " | Profit = ", profit); break; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void checkTPSLHit() { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); for(int i = 0; i < MaxOrders; i++) { if(od[i].trade_ticket != -1 && od[i].trade_close_price == 0) { int ticket = od[i].trade_ticket; int type = od[i].trade_type; double sl = od[i].trade_sl; double tp = od[i].trade_tp; double closePrice = 0; // ---------------------------------------------- // BUY ORDER CHECK // ---------------------------------------------- if(type == 0) { // TP hit → Bid >= TP if(bid >= tp && tp > 0) { closePrice = bid; Print(" ======== Buy Trade TP Hit ======= ",ticket); } // SL hit → Bid <= SL if(bid <= sl && sl > 0) { closePrice = bid; Print(" ======== Buy Trade SL Hit ======= ",ticket); } } // ---------------------------------------------- // SELL ORDER CHECK // ---------------------------------------------- if(type == 1) { // TP hit → Ask <= TP (price goes DOWN) if(ask <= tp && tp > 0) { closePrice = ask; Print(" ======== Sell Trade TP Hit ======= ",ticket); } // SL hit → Ask >= SL if(ask >= sl && sl > 0) { closePrice = ask; Print(" ======== Sell Trade SL Hit ======= ",ticket); } } // ---------------------------------------------- // IF ANYTHING TRIGGERED → CLOSE TRADE // ---------------------------------------------- if(closePrice > 0) { od[i].trade_close_price = closePrice; od[i].trade_close_time = TimeCurrent(); double tpdifference = type == 1 ? (od[i].trade_open_price - od[i].trade_close_price) / Point() : (od[i].trade_close_price - od[i].trade_open_price) / Point(); od[i].trade_profit += tpinDollar(od[i].trade_lot, tpdifference); Print("======= TRADE CLOSED of ticket =======",ticket); Print("Index: ", i, " | Ticket: ", ticket, " | Type: ", type, " | ClosePrice: ", closePrice, " | Time: ", od[i].trade_close_time, " | Profit: ", od[i].trade_profit); tpSlHit = false; // make these zero so new trade place's string line = MakeTradeString( od[i].trade_ticket, od[i].trade_type, od[i].trade_magic_no, od[i].trade_open_price, od[i].trade_close_price, od[i].trade_open_time, od[i].trade_close_time, od[i].trade_sl, od[i].trade_tp, od[i].trade_lot, od[i].trade_profit ); writeDatainFile(line); } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double tpinDollar(double lotSize, double distance) { double pipvalue = NormalizeDouble(((SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)/(SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_SIZE)/Point()))*10),2); pipvalue = pipvalue / 10; double dollar = lotSize * distance * pipvalue; return NormalizeDouble(dollar,2); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void writeDatainFile(string str) { int filehandle = FileOpen(fileName,FILE_WRITE|FILE_CSV|FILE_COMMON|FILE_END,","); if(filehandle != INVALID_HANDLE) { FileSeek(filehandle, 0, SEEK_END); FileWrite(filehandle,str); Print(str); FileClose(filehandle); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ string MakeTradeString(int ticket, int type, int magic, double open_price, double close_price, datetime open_time, datetime close_time, double sl, double tp, double lotSize, double profit) { string str = StringFormat("%d,%d,%d,%.5f,%.5f,%s,%s,%.5f,%.5f,%.2f,%.2f", ticket, type, magic, open_price, close_price, TimeToString(open_time, TIME_DATE|TIME_SECONDS), TimeToString(close_time, TIME_DATE|TIME_SECONDS), sl, tp, lotSize, profit); return str; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void setStart_EndTime(bool onInit,string start,string end,datetime & sessionStart,datetime & sessionEnd) { int newYorkStartHour = 0, newYorkStartMin = 0, newYorkEndHour = 0, newYorkEndMin = 0; datetime newYorkStartTrading,newYorkEndTrading; string time[]; StringSplit(start,':',time); newYorkStartHour = (int)StringToInteger(time[0]); newYorkStartMin = (int)StringToInteger(time[1]); EventSetMillisecondTimer(500); time[0] = ""; time[1] = ""; StringSplit(end,':',time); newYorkEndHour = (int)StringToInteger(time[0]); newYorkEndMin = (int)StringToInteger(time[1]); // Print(" Start Time Hour: ",newYorkStartHour," Start Time Min: ",newYorkStartMin); // Print(" End Time Hour: ",newYorkEndHour," End Time Min: ",newYorkEndMin); datetime startDateTime; MqlDateTime st; TimeCurrent(st); // get current date st.hour = newYorkStartHour; st.min = newYorkStartMin; st.sec = 0; startDateTime = StructToTime(st); datetime endDateTime; MqlDateTime et; TimeCurrent(et); // get current date et.hour = newYorkEndHour; et.min = newYorkEndMin; et.sec = 0; endDateTime = StructToTime(et); MqlDateTime sdate,edate; datetime start_Time = 0, end_Time = 0; if(startDateTime > endDateTime) { if(onInit) { start_Time = iTime(Symbol(),PERIOD_D1,1); end_Time = iTime(Symbol(),PERIOD_D1,0); } else { start_Time = sessionStart; end_Time = sessionEnd; if(TimeCurrent() >= sessionEnd && sessionEnd != 0) { start_Time = iTime(Symbol(),PERIOD_D1,0); end_Time = start_Time + 86400; } } } else { start_Time = iTime(Symbol(),PERIOD_D1,0); end_Time = iTime(Symbol(),PERIOD_D1,0); } if(TimeToStruct(end_Time,edate)) { edate.hour = newYorkEndHour; edate.min = newYorkEndMin; edate.sec = 0; } else Print("Error in Converting Time: ",GetLastError()); newYorkEndTrading = StructToTime(edate); if(TimeToStruct(start_Time,sdate)) { sdate.hour = newYorkStartHour; sdate.min = newYorkStartMin; sdate.sec = 0; } else Print("Error in Converting Time: ",GetLastError()); newYorkStartTrading = StructToTime(sdate); sessionStart = newYorkStartTrading; sessionEnd = newYorkEndTrading; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void setStart_EndTime_modify(bool onInit,string start,string end,datetime & sessionStart,datetime & sessionEnd) { int newYorkStartHour = 0, newYorkStartMin = 0, newYorkEndHour = 0, newYorkEndMin = 0; datetime newYorkStartTrading,newYorkEndTrading; string time[]; StringSplit(start,':',time); newYorkStartHour = (int)StringToInteger(time[0]); newYorkStartMin = (int)StringToInteger(time[1]); time[0] = ""; time[1] = ""; StringSplit(end,':',time); newYorkEndHour = (int)StringToInteger(time[0]); newYorkEndMin = (int)StringToInteger(time[1]); // Print(" Start Time Hour: ",newYorkStartHour," Start Time Min: ",newYorkStartMin); // Print(" End Time Hour: ",newYorkEndHour," End Time Min: ",newYorkEndMin); datetime startDateTime; MqlDateTime st; TimeCurrent(st); // get current date st.hour = newYorkStartHour; st.min = newYorkStartMin; st.sec = 0; startDateTime = StructToTime(st); datetime endDateTime; MqlDateTime et; TimeCurrent(et); // get current date et.hour = newYorkEndHour; et.min = newYorkEndMin; et.sec = 0; endDateTime = StructToTime(et); MqlDateTime sdate,edate; datetime start_Time = 0, end_Time = 0; if(startDateTime > endDateTime) { start_Time = iTime(Symbol(),PERIOD_D1,1); end_Time = iTime(Symbol(),PERIOD_D1,0); } else { start_Time = iTime(Symbol(),PERIOD_D1,0); end_Time = iTime(Symbol(),PERIOD_D1,0); } if(TimeToStruct(end_Time,edate)) { edate.hour = newYorkEndHour; edate.min = newYorkEndMin; edate.sec = 0; } else Print("Error in Converting Time: ",GetLastError()); newYorkEndTrading = StructToTime(edate); if(TimeToStruct(start_Time,sdate)) { sdate.hour = newYorkStartHour; sdate.min = newYorkStartMin; sdate.sec = 0; } else Print("Error in Converting Time: ",GetLastError()); newYorkStartTrading = StructToTime(sdate); sessionStart = newYorkStartTrading; sessionEnd = newYorkEndTrading; } //+------------------------------------------------------------------+ //| Check Virtual TP/SL for all positions | //+------------------------------------------------------------------+ void CheckVirtualGlobalTpSl() { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); for(int i=PositionsTotal()-1; i >=0 ; i--) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC) == magicNo && PositionGetString(POSITION_SYMBOL) == _Symbol) { if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { double tp_price = PositionGetDouble(POSITION_PRICE_OPEN) + glTp * 10 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); double sl_price = PositionGetDouble(POSITION_PRICE_OPEN) - glSl * 10 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); if(bid >= tp_price || bid <= sl_price) { closeAllActiveOrders(); return; } } if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { double tp_price = PositionGetDouble(POSITION_PRICE_OPEN) - glTp * 10 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); double sl_price = PositionGetDouble(POSITION_PRICE_OPEN) + glSl * 10 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); if(ask <= tp_price || ask >= sl_price) { closeAllActiveOrders(); return; } } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CheckDailyDrawdown() { if(!UseDailyDrawdownLimit) return; double equity = AccountInfoDouble(ACCOUNT_EQUITY); double drawdown = g_dailyStartBalance - equity; if(drawdown >= DailyDrawdownAmount) { Print("Daily Drawdown Limit Hit: ", drawdown, " >= ", DailyDrawdownAmount); closeAllActiveOrders(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void markClosedOrder(datetime eaTime) { HistorySelect(eaTime, TimeCurrent()); for(int i = HistoryDealsTotal() - 1; i >= 0; i--) { ulong dealTicket = HistoryDealGetTicket(i); long dealMagic = HistoryDealGetInteger(dealTicket, DEAL_MAGIC); if(dealMagic != magicNo && dealMagic != 0) continue; if(HistoryDealGetString(dealTicket, DEAL_SYMBOL) == Symbol()) { //Print("Condition 2 ",HistoryDealGetInteger(dealTicket, DEAL_ENTRY)," HistoryDealsTotal(): ",HistoryDealsTotal()); if(HistoryDealGetInteger(dealTicket, DEAL_ENTRY) == DEAL_ENTRY_OUT) { //Print("deal out close: ",dealTicket); long dealType = HistoryDealGetInteger(dealTicket, DEAL_TYPE); if(dealType != DEAL_TYPE_BUY && dealType != DEAL_TYPE_SELL) continue; double profit = HistoryDealGetDouble(dealTicket, DEAL_PROFIT); profit = NormalizeDouble(profit, 2); string lineName = "TradeLine_" + (string)dealTicket; if(ObjectFind(0, lineName) >= 0) continue; ulong entryDeal = findEntryDeal(dealTicket); if(entryDeal == 0) continue; datetime openTime = (datetime)HistoryDealGetInteger(entryDeal, DEAL_TIME); double openPrice = HistoryDealGetDouble(entryDeal, DEAL_PRICE); datetime closeTime = (datetime)HistoryDealGetInteger(dealTicket, DEAL_TIME); double closePrice = HistoryDealGetDouble(dealTicket, DEAL_PRICE); createTrendLine(lineName, openTime, openPrice, closeTime, closePrice, dealType, profit); PrintFormat("Trend line created for closed trade #%I64u | Profit: %.2f", dealTicket, profit); } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void createTrendLine(string name, datetime openTime, double openPrice, datetime closeTime, double closePrice, long dealType, double profit) { if(ObjectFind(0, name) >= 0) return; if(!ObjectCreate(0, name, OBJ_TREND, 0, openTime, openPrice, closeTime, closePrice)) { Print("Error creating trend line: ", GetLastError()); return; } ObjectSetInteger(0, name, OBJPROP_WIDTH, tradeLineThickness); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, name, OBJPROP_RAY, false); color lineColor = (dealType == DEAL_TYPE_BUY) ? clrRed : clrBlue; ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor); createProfitLabel(name + "_label", openTime, openPrice, closeTime, closePrice, dealType, profit); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void createProfitLabel(string name, datetime openTime, double openPrice, datetime closeTime, double closePrice, long dealType, double profit) { if(ObjectFind(0, name) >= 0) return; datetime middleTime = openTime + (closeTime - openTime) / 2; double midPrice = (openPrice + closePrice) / 2; if(!ObjectCreate(0, name, OBJ_TEXT, 0, middleTime, midPrice)) { Print("Error creating profit label: ", GetLastError()); return; } string profitText = "$" + DoubleToString(profit, 2); ObjectSetString(0, name, OBJPROP_TEXT, profitText); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, dollarFontSize); ObjectSetInteger(0, name, OBJPROP_COLOR, dollarFontColor); ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ ulong findEntryDeal(ulong closeDeal) { string symbol = HistoryDealGetString(closeDeal, DEAL_SYMBOL); long positionID = HistoryDealGetInteger(closeDeal, DEAL_POSITION_ID); int dealOutCount = 0; for(int i = HistoryDealsTotal() - 1; i >= 0; i--) { ulong deal = HistoryDealGetTicket(i); if(HistoryDealGetInteger(deal, DEAL_POSITION_ID) == positionID) { if(HistoryDealGetInteger(deal, DEAL_ENTRY) == DEAL_ENTRY_OUT) { dealOutCount++; } } } if(dealOutCount < 2) { for(int i = HistoryDealsTotal() - 1; i >= 0; i--) { ulong deal = HistoryDealGetTicket(i); if(HistoryDealGetInteger(deal, DEAL_POSITION_ID) == positionID && HistoryDealGetInteger(deal, DEAL_ENTRY) == DEAL_ENTRY_IN && HistoryDealGetString(deal, DEAL_SYMBOL) == symbol) return deal; //Print("Deal: ", deal); } } else { for(int i = 0; i < HistoryDealsTotal(); i++) { ulong deal = HistoryDealGetTicket(i); if(HistoryDealGetInteger(deal, DEAL_POSITION_ID) == positionID && HistoryDealGetInteger(deal, DEAL_ENTRY) == DEAL_ENTRY_OUT) { return deal; } //Print("Deal: ", deal); } } return 0; } //+------------------------------------------------------------------+