//+------------------------------------------------------------------+
//|                                                 Symphonie EA.mq4 |
//|                                                          MeAgain |
//|                                                                  |
//+------------------------------------------------------------------+
#include <stderror.mqh>
#include <stdlib.mqh>

#property copyright "MeAgain"
#property link      ""

double d_LotSize;                       // Size of a contract, based on the FreeMargin
double d_MaxPivotDistPippetes = 200;    // Contains maximum distance to a pivot in pippets
double d_MaxPivotDist;                  // Contains actual distance to a pivot
double d_Risk = 1;                      // Indicates maximum risk to take in % of equity
double d_StopLoss;                      // Contains actual stop loss value
double d_StopLossPippetes = 1000;       // Contains stop loss value in pippets
double d_TakeProfit;                    // Contains actual take profit value
double d_TakeProfitPippetes = 100;      // Contains take profit value in pippets

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
   // Convert pip values to currency value...
   ConvertPipValues();
   
   // Delete all closed trades from the chart...
   DeleteClosedTrades();
   
   // Draw trades in chart...
   DrawClosedTrades();
   
   return(0);
}
  
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
   return(0);
}
  
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
   // Monitor existing trades, if there is one, exit when done checking...
   if (OrderExists()) {
      MonitorTrade();
      
      // The order exists, and is being monitored, no need to carry on...
      return;
   }

   // Trading is only allowed during the Frankfurt/London/New York session, which is
   // between 0700 and 2200 hours Dutch summer time... (CHECK THIS)
   if (!TradingAllowed()) {
      return;
   }

   ////
   // This point is only reached when there is no open order and trading is allowed.
   //
   // On each subject a check is executed. When there is no signal the code returns
   // for performance reasons. If the signal is valid, the next signal is being verified.
   ////
   
   // Get signal from Symphonie...
   string SymphonieSignal = SymphonieSignal();

   // Return when there is no Symphonie signal...
   if (SymphonieSignal == "NONE") {
      return;
   }
   
   // Return if there is not enough distance to the closest Pivot...
   if (!PivotsOK( SymphonieSignal )) {
      return;
   }
   
   // Return if the Stochastic is Overbought/Oversold or in the wrong direction...
   if (!StochOK( SymphonieSignal )) {
      return;
   }
   
   // Return if the Average Daily Range is already exhausted...
   if (!AdrOK()) {
      return;
   }
   
   ////
   // If this point is reached all requirements are fullfilled and
   // an order can be placed...
   ////

   // First, calculate the lotsize lotsize...
   CalculateLotSize();
   
   // Finally create the order...
   OpenOrder( SymphonieSignal, d_LotSize );
   
   ////
   // If this point is reached the order is placed and all closed trades can be
   // drawn in the chart.
   ////
   
   // Delete all closed trades from the chart...
   DeleteClosedTrades();
   
   // Draw trades in chart...
   DrawClosedTrades();
}
//+------------------------------------------------------------------+

bool TradingAllowed()
{
   // Trading is only allowed during Frankfurt/London/New York opening...
   if (Hour()>07 && Hour()<22) {
      return (true);

   } else {
      return (false);
   }
}

/*
This procedure checks if the Average Daily Range is not exhousted.
*/
bool AdrOK()
{
   double Sum=0;
   double NumOfDays=10;

   // Loop over the last NumOfDays closed daily candles...
   for (int i=1; i<=NumOfDays; i++)  {

      // Get the high and low for this candle...
      double Hi = iHigh( NULL, PERIOD_D1, i );
      double Lo = iLow( NULL, PERIOD_D1, i );
      
      // Add delta to the sum...
      Sum += Hi-Lo;
   }
  
   // Now, get the high and low for the open candle...
   Hi = iHigh( NULL,PERIOD_D1, 0 );
   Lo = iLow( NULL,PERIOD_D1, 0 );
   
   double SumPips = (Sum/NumOfDays)*10000;
   double TodayPips = (Hi-Lo)*10000;

   // To scalp 10 PIPs there has to be a range of at leased 30 PIPs...
   if (TodayPips < SumPips-30) {
      return (true);
   } else {
      LogIt( Symbol() + " ADR is already completed" );
      
      return (false);
   }
}

/*
This procedure calculates the lot size for new trades. The lot size is calculated
based on Risk and StopLoss...
*/
void CalculateLotSize()
{
   double d_MinLotSize = MarketInfo( Symbol(), MODE_MINLOT );
  
   d_LotSize = AccountFreeMargin() * d_Risk/100 / (d_StopLossPippetes * MarketInfo( Symbol(), MODE_TICKVALUE ));
   
   // Minimum lot size is 0.1...
   if (d_LotSize < d_MinLotSize) {
      d_LotSize = d_MinLotSize;
   }
}

bool StochOK(string Direction)
{
   double M_0, M_1,               // Value MAIN on 0 and 1st bars
          S_0, S_1;               // Value SIGNAL on 0 and 1st bars
   string StochDirection;

   // Stochastic values, M is the green line, S is the redline...
   M_0 = iStochastic(NULL, 0, 5, 3, 3, MODE_SMA, 0, MODE_MAIN, 0);
   M_1 = iStochastic(NULL, 0, 5, 3, 3, MODE_SMA, 0, MODE_MAIN, 1);
   S_0 = iStochastic(NULL, 0, 5, 3, 3, MODE_SMA, 0, MODE_SIGNAL, 0);
   S_1 = iStochastic(NULL, 0, 5, 3, 3, MODE_SMA, 0, MODE_SIGNAL, 1);

   // Green line is above red line and climbing...
   if (M_0 > S_0 && M_0 >= M_1) {
      StochDirection = "LONG";
   }
   
   // Green line is below red line and going down...
   if (M_0 < S_0 && M_0 <= M_1) {
      StochDirection = "SHORT";
   }
   
   if (M_0 > 80) {
      StochDirection = "OVERBOUGHT";
   }
   
   if (M_0 < 20) {
      StochDirection = "OVERSOLD";
   }
 
   if (StochDirection == Direction) {
      return (true);
   } else {
      LogIt( Symbol() + " stochastic is " + StochDirection );
      return (false);
   }
}

/*
   This procedure checks if there is enough room for the currency pair to
   to move, before it hits a major resistance.
*/
bool PivotsOK(string Direction)
{
   // Loop over all objects...
   for(int i=ObjectsTotal()-1; i>=0; i--) {

      // Returns -1 if substring is not found, otherwise it returns the 
      // position of the first character. If it is a pivot line it should
      // return 0...
      int index=StringFind( ObjectName(i), "PivotsLHDT_Daily", 0 );
      
      // Right, only pivot lines go in here...
      if (index==0 && ObjectDescription(ObjectName(i)) == "") {

         // Calculate crossing point of open candle with pivot line...
         double Cross = ObjectGet( ObjectName(i), OBJPROP_PRICE1 );
         
         // For longs, only take the pivots above the price...
         if (Direction == "LONG") {
            double Diff;
            
            if (Cross > Ask) {
               // Difference between crossing point and open price...
               Diff = MathAbs(Cross - Ask);
               
               // Stop searching, found pivot which is too close...
               if (Diff < d_MaxPivotDist) {
                  LogIt( Symbol() + " " + ObjectName(i) + " too close " + DoubleToStr(Diff, 5) );
                  return(false);
               }
            }
         
         // For shorts, only take the pivots below the price...
         } else if (Direction == "SHORT") {
            if (Cross < Bid) {
               // Difference between crossing point and open price...
               Diff = MathAbs(Cross - Bid);
               
               // Stop searching, found pivot which is too close...
               if (Diff > d_MaxPivotDist) {
                  LogIt( Symbol() + " " + ObjectName(i) + " too close " + Diff );
                  
                  return(false);
               }
            }
         }
      }
   }
   
   // When this point is reached, all pivots are far away...
   return(true);
}

void MonitorTrade()
{
   double NewOrderTakeProfit;
   double NewOrderStopLoss;
   
   // Loop over all orders...
   for(int i=0; i<OrdersTotal(); i++)
   {
      // Select this order...
      if (OrderSelect(i, SELECT_BY_POS) == true) {
      
         // Yes, order is found...
         if (OrderSymbol() == Symbol()) {
            
            // Set stop loss and take profit if they are not set...
            if (OrderStopLoss() == 0) {
               
               // Put a stop loss and take profit on the order...
               if (OrderType() == OP_BUY) {
                  NewOrderStopLoss = OrderOpenPrice() - d_StopLoss;
                  NewOrderTakeProfit = OrderOpenPrice() + d_TakeProfit;

               } else if (OrderType() == OP_SELL) {
                  NewOrderStopLoss = OrderOpenPrice() + d_StopLoss;
                  NewOrderTakeProfit = OrderOpenPrice() - d_TakeProfit;
               }
               
               ModifyOrder( OrderTicket(), NewOrderStopLoss, NewOrderTakeProfit );
            }

            // Close trade when signal on H1 time frame is gone...
            if ((OrderType() == OP_BUY) && (H1ExtremeSignal() != "LONG_EXTREME")) {
               CloseOrder( OrderTicket(), OrderLots() );
            
            } else if ((OrderType() == OP_SELL) && (H1ExtremeSignal() != "SHORT_EXTREME")) {
               CloseOrder( OrderTicket(), OrderLots() );
            }
         }
      }
   }
}

void CloseOrder(int OrderNumber, double OrderSize)
{
   bool ReturnValue;
   
   if (OrderType() == OP_BUY) {
      ReturnValue = OrderClose( OrderNumber, OrderSize, Bid, 2, Blue );
           
   } else {
      ReturnValue = OrderClose( OrderNumber, OrderSize, Ask, 2, Red );
   }
      
   // Raise error message...
   if (ReturnValue == false){
      int ErrorCode = GetLastError();
      
      // Text to be logged...
      LogIt( "OrderClose " + OrderNumber + " failed with ErrorCode: " + ErrorCode + " - ErrorText: " + ErrorDescription(ErrorCode) );

   } else if (ReturnValue == true) {
      // Text to be logged...
      LogOrderInfo( "Close", OrderNumber );
   }
}

/*
   This procedure checks if a signal is still available on the H1 time frame...
*/
string H1ExtremeSignal()
{
   // Define variables...
   int Handle;

   // Construct filename signalling files...
   string H1ShortExtremeSignalFileName = StringConcatenate( Symbol(), "_SHORT_EXTREME_H1.sgn" );
   string H1LongExtremeSignalFileName = StringConcatenate( Symbol(), "_LONG_EXTREME_H1.sgn" );

   ////
   // Check if there is an Long Extreme signal on H1...
   ////
   Handle = FileOpen( H1LongExtremeSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      // Close file...
      FileClose(Handle);
      
      // Signal found, stop searching...
      return ("LONG_EXTREME");
   }

   ////
   // Check if there is a Short signal on H1...
   ////
   Handle = FileOpen( H1ShortExtremeSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      
      // Close file...
      FileClose(Handle);
      
      // Signal found, stop searching...
      return ("SHORT_EXTREME");
   }
   
   // No signals found...  
   return ("NONE");
}

void ModifyOrder(int NewOrderNumber, double NewOrderStopLoss, double NewOrderTakeProfit)
{
   bool ReturnValue;

   // Set StopLoss values...
   ReturnValue = OrderModify(NewOrderNumber, NULL, NewOrderStopLoss, NewOrderTakeProfit, 3, Blue);

   // Raise error message for OrderModify...
   if (ReturnValue == false) {
      int ErrorCode = GetLastError();
      
      // Text to be logged...
      LogIt( "OrderModify " + NewOrderNumber + " failed with ErrorCode: " + ErrorCode + " - ErrorText: " + ErrorDescription(ErrorCode) );
   
   } else if (ReturnValue == true) {
      // Text to be logged...
      LogOrderInfo( "Modify", NewOrderNumber );
   }
}

void ConvertPipValues()
{
   // Convert PIP values for JPY currency pairs...
   if (Point == 0.00100) {
      
      d_MaxPivotDist = NormalizeDouble(d_MaxPivotDistPippetes/1000, 3);
      d_StopLoss = NormalizeDouble(d_StopLossPippetes/1000, 3);
      d_TakeProfit = NormalizeDouble(d_TakeProfitPippetes/1000, 3);
   
   // Convert PIP values for other currency pairs...
   } else if (Point == 0.00001) {
      d_MaxPivotDist = NormalizeDouble(d_MaxPivotDistPippetes/100000, 5);
      d_StopLoss = NormalizeDouble(d_StopLossPippetes/100000, 5);
      d_TakeProfit = NormalizeDouble(d_TakeProfitPippetes/100000, 5);
   }
}

bool OrderExists()
{
   // Loop over all orders...
   for(int i=0; i<OrdersTotal(); i++)
   {
      // Select this order...
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true) {
      
         // Yes, order is found...
         if (OrderSymbol() == Symbol()) {
            return (true);
         }
      }
   }
   
   // No, order not found...
   return (false);
}

string SymphonieSignal()
{
   // Define variables...
   int Handle;
   
   bool H1ShortExtremeSignal = false;
   bool H1ShortCombiSignal = false;
   bool H1LongExtremeSignal = false;
   bool H1LongCombiSignal = false;
   
   bool M5ShortExtremeSignal = false;
   bool M5ShortCombiSignal = false;
   bool M5LongExtremeSignal = false;
   bool M5LongCombiSignal = false;
   
   // Construct filename signalling files...
   string H1ShortExtremeSignalFileName = StringConcatenate( Symbol(), "_SHORT_EXTREME_H1.sgn" );
   string H1ShortCombiSignalFileName = StringConcatenate( Symbol(), "_SHORT_COMBI_H1.sgn" );
   string H1LongExtremeSignalFileName = StringConcatenate( Symbol(), "_LONG_EXTREME_H1.sgn" );
   string H1LongCombiSignalFileName = StringConcatenate( Symbol(), "_LONG_COMBI_H1.sgn" );
   
   string M5ShortExtremeSignalFileName = StringConcatenate( Symbol(), "_SHORT_EXTREME_M5.sgn" );
   string M5ShortCombiSignalFileName = StringConcatenate( Symbol(), "_SHORT_COMBI_M5.sgn" );
   string M5LongExtremeSignalFileName = StringConcatenate( Symbol(), "_LONG_EXTREME_M5.sgn" );
   string M5LongCombiSignalFileName = StringConcatenate( Symbol(), "_LONG_COMBI_M5.sgn" );

   ////
   // Check if there is a Short Extreme signal on H1...
   ////
   Handle = FileOpen( H1ShortExtremeSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      H1ShortExtremeSignal = true;
      
      // Close file...
      FileClose(Handle);
   }
   
   ////
   // Check if there is a Short Extreme signal on H1...
   ////
   Handle = FileOpen( H1ShortCombiSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      H1ShortCombiSignal = true;
      
      // Close file...
      FileClose(Handle);
   }   

   ////
   // Check if there is a Short Extreme signal on H1...
   ////
   Handle = FileOpen( H1LongExtremeSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      H1LongExtremeSignal = true;
      
      // Close file...
      FileClose(Handle);
   }  
   
   ////
   // Check if there is a Short Extreme signal on H1...
   ////
   Handle = FileOpen( H1LongCombiSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      H1LongCombiSignal = true;
      
      // Close file...
      FileClose(Handle);
   }
   
   ////
   // Check if there is a Short Extreme signal on H1...
   ////
   Handle = FileOpen( M5ShortExtremeSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      M5ShortExtremeSignal = true;
      
      // Close file...
      FileClose(Handle);
   }

   ////
   // Check if there is a Short Extreme signal on H1...
   ////
   Handle = FileOpen( M5ShortCombiSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      M5ShortCombiSignal = true;
      
      // Close file...
      FileClose(Handle);
   }

   ////
   // Check if there is a Short Extreme signal on H1...
   ////
   Handle = FileOpen( M5LongExtremeSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      M5LongExtremeSignal = true;
      
      // Close file...
      FileClose(Handle);
   }
   
   ////
   // Check if there is a Short Extreme signal on H1...
   ////
   Handle = FileOpen( M5LongCombiSignalFileName, FILE_CSV|FILE_READ );
   
   // Check if signal file exists...
   if (Handle > 0) {
      M5LongCombiSignal = true;
      
      // Close file...
      FileClose(Handle);
   }
   
   // There is a Symphonie Long signal, give go for trade...
   if ( M5LongExtremeSignal && M5LongCombiSignal && H1LongExtremeSignal && H1LongCombiSignal) {
      LogIt( Symbol() + " Symphonie LONG " + DoubleToStr(Bid, 5) );
   
      return ("LONG");
   }
   
   // There is a Symphonie Short signal, give go for trade...
   if (M5ShortExtremeSignal && M5ShortCombiSignal && H1ShortExtremeSignal && H1ShortCombiSignal) {
      LogIt( Symbol() + " Symphonie SHORT " + DoubleToStr(Ask, 5) );

      return ("SHORT");
   }
   
   return ("NONE");
}

/*
   This procedure creates the required order. Any logic which determines the lot size is done on
   a higher level.
   
   It is not possible for marktorders to set the stop loss with the OrderSend command.
*/
void OpenOrder(string NewOrderType, double NewOrderSize)
{
   int NewOrderNumber;

   // Open order...
   if (NewOrderType == "LONG") {
      NewOrderNumber = OrderSend(Symbol(), OP_BUY, NewOrderSize, Ask, 3, NULL, NULL, NULL, NULL, 0, Blue);

   } else if (NewOrderType == "SHORT") {
      NewOrderNumber = OrderSend(Symbol(), OP_SELL, NewOrderSize, Bid, 3, NULL, NULL, NULL, NULL, 0, Red);
   }

   // Write something usefull in the log...
   if (NewOrderNumber < 0) {
      int ErrorCode = GetLastError();
      
      // Log text to file...
      LogIt( "OrderSend failed with ErrorCode: " + ErrorCode + " - ErrorText: " + ErrorDescription(ErrorCode) );
      
   } else {
      // Send an email...
      SendMail( Symbol() + " Symph " + NewOrderType + " order created", "" );
      
      // Text to be logged...
      LogOrderInfo( "Open", NewOrderNumber );
   }
}

void LogIt(string Line)
{
   int CurrentYear = Year();
   string TimeStamp = TimeToStr( TimeCurrent(), TIME_DATE|TIME_SECONDS );

   // Construct filename for logging...
   string FileName = StringConcatenate( CurrentYear, "_", Symbol(), ".log" );

   // Construct logged line...
   string LogLine = StringConcatenate( TimeStamp, " ", Line );

   // Open file for reading and writing...
   int Handle = FileOpen( FileName, FILE_CSV|FILE_READ|FILE_WRITE );
   
   if (Handle > 0) {
      // Go to End Of File...
      FileSeek(Handle, 0, SEEK_END);
      
      // Write line to file...
      FileWrite(Handle, LogLine);
      
      // Finally close file...
      FileClose(Handle);
   }
}

void LogOrderInfo(string Action, int OrderNumber)
{
   // Select this order...
   if (OrderSelect(OrderNumber, SELECT_BY_TICKET) == true) {
   
      string OrderLogType;
      
      // Convert to a string value...
      if (OrderType() == 1) {
         OrderLogType = "SELL";

      } else if (OrderType() == 0) {
         OrderLogType = "BUY";
      }
      
      // Get prices in 5 digits...
      string OrderLogOpenPrice = DoubleToStr( OrderOpenPrice(), 5);
      string OrderLogStopLoss = DoubleToStr( OrderStopLoss(), 5);
      string OrderLogTakeProfit = DoubleToStr( OrderTakeProfit(), 5);
      string OrderLogClosePrice = DoubleToStr( OrderClosePrice(), 5);
      string OrderSize = DoubleToStr( OrderLots(), 2);

      // Print order information to log...
      if (Action == "Open") {
         LogIt( "Open #"+ OrderNumber + " " + OrderLogType + " " + OrderSize + " " + Symbol() + " at " + OrderLogOpenPrice + " ok" );

      } else if (Action == "Modify") {
         LogIt( "Modify #" + OrderNumber + " " + OrderLogType + " " + OrderSize + " " + Symbol() + " at " + OrderLogOpenPrice + " sl:" + OrderLogStopLoss + " tp:" + OrderLogTakeProfit + " ok" );

      } else if (Action == "Close") {
         LogIt( "Close #" + OrderNumber + " " + OrderLogType + " " + OrderSize + " " + Symbol() + " at " + OrderLogOpenPrice + " sl:" + OrderLogStopLoss + " tp:" + OrderLogTakeProfit + " at price " + OrderLogClosePrice );
      }
      
   } else {
      int ErrorCode = GetLastError();

      // Log text to file...
      LogIt( "OrderSelect failed with ErrorCode: " + ErrorCode + " - ErrorText: " + ErrorDescription(ErrorCode) );
   }
}

void DeleteClosedTrades()
{
}

/*
This procedure draws all closed trades into the chart.

Main reason for this is that MetaTrader does not trades in the chart when it hits a
stop loss or take profit.
*/
void DrawClosedTrades()
{
   // Loop over history...
   for(int i=0; i<OrdersHistoryTotal(); i++)
   {
      // Select this order...
      if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == true) {

         // Carry on if currency is correct...
         if (OrderSymbol()==Symbol()) {

            // Draw the closed trade in the chart...
            PlotOpenedTradeArrow(OrderTicket());
      
            PlotClosedTradeArrow(OrderTicket());
      
            PlotClosedTradeLine(OrderTicket());
         }
      }
   }
}

void PlotOpenedTradeArrow(int i_ticket)
{
   // Select this order...
   OrderSelect(i_ticket, SELECT_BY_TICKET);

   // Return for canceled pending orders...
   if (OrderType() == OP_SELLSTOP || OrderType() == OP_BUYSTOP) {
      return;
   }
   
   // Configure name for the open arrow...
   string s_Name;
   if (OrderType() == OP_SELL) {
      s_Name = "Open SELL " + i_ticket;
   
   } else if (OrderType() == OP_BUY) {
      s_Name = "Open BUY " + i_ticket;
   }
   
   // Create Object...
   ObjectCreate(s_Name, OBJ_ARROW, 0, OrderOpenTime(), OrderOpenPrice());
   ObjectSet(s_Name, OBJPROP_ARROWCODE, 1);
   
   if (OrderType() == OP_SELL) {
      ObjectSet(s_Name, OBJPROP_COLOR, Red);
   
   } else if (OrderType() == OP_BUY) {
      ObjectSet(s_Name, OBJPROP_COLOR, Blue);
   }
}

void PlotClosedTradeArrow(int i_ticket)
{
   // Select this order...
   OrderSelect(i_ticket, SELECT_BY_TICKET);

   // Return for canceled pending orders...
   if (OrderType() == OP_SELLSTOP || OrderType() == OP_BUYSTOP) {
      return;
   }
   
   // Configure name for the close arrow...
   string s_Name;
   if (OrderType() == OP_SELL) {
      s_Name = "Close SELL " + i_ticket;
   
   } else if (OrderType() == OP_BUY) {
      s_Name = "Close BUY " + i_ticket;
   }

   // Create Object...
   ObjectCreate(s_Name, OBJ_ARROW, 0, OrderCloseTime(), OrderClosePrice());
   ObjectSet(s_Name, OBJPROP_ARROWCODE, 3);
   
   if (OrderType() == OP_SELL) {
      ObjectSet(s_Name, OBJPROP_COLOR, Red);
   
   } else if (OrderType() == OP_BUY) {
      ObjectSet(s_Name, OBJPROP_COLOR, Blue);
   }
}

void PlotClosedTradeLine(int i_ticket)
{
   // Select this order...
   OrderSelect(i_ticket, SELECT_BY_TICKET);

   // Return for canceled pending orders...
   if (OrderType() == OP_SELLSTOP || OrderType() == OP_BUYSTOP) {
      return;
   }
   
   // Configure name for the line...
   string s_Name;
   double d_OrderProfit = OrderProfit() + OrderSwap() + OrderCommission();
   
   if (OrderType() == OP_SELL) {
      s_Name = "Line SELL " + i_ticket + " P/l=" + d_OrderProfit;
   
   } else if (OrderType() == OP_BUY) {
      s_Name = "Line BUY " + i_ticket + " P/l=" + d_OrderProfit;
   }
   
   // Create Object...
   ObjectCreate(s_Name, OBJ_TREND, 0, OrderOpenTime(), OrderOpenPrice(), OrderCloseTime(), OrderClosePrice());
   ObjectSet(s_Name, OBJPROP_RAY, false);
   ObjectSet(s_Name, OBJPROP_STYLE, STYLE_DOT);
   
   if (OrderType() == OP_SELL) {
      ObjectSet(s_Name, OBJPROP_COLOR, Red);
   
   } else if (OrderType() == OP_BUY) {
      ObjectSet(s_Name, OBJPROP_COLOR, Blue);
   }
}