//+------------------------------------------------------------------+




#property copyright "Ivan."
#property link      ""
#property version   "1.00"
#property strict


extern double Lots      = 0.1;
extern int StopLoss     = 20;
extern int TakeProfit   = 5000;
extern int TrailingStop = 20;
extern int Slippage     = 3;
extern int Magic        = 123;

extern int MinDiff      = 5;
// Money management
extern bool UseMM = false;
// Amount of lots per every 10,000 of free margin
extern double LotsPer10000 = 1;

extern bool ECN_Mode = false; // In ECN mode, SL and TP aren't applied on OrderSend() but are added later with OrderModify()

double Poin;
int Deviation;

int LastBars = 0;

//0 - undefined, 1 - bullish cross (h1), -1 - bearish cross (l1)
int PrevCross = 0;


//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int init()
{
 
	Poin = Point;
	
  
   if ((Digits == 3) || (Digits == 5))
   {
      TakeProfit  *= 10;
      StopLoss    *= 10;
      Slippage    *= 10;
   }

   return(0);
}

//+------------------------------------------------------------------+
//| Start function                                                   |
//+------------------------------------------------------------------+
void start()
{
   if (TrailingStop > 0) DoTrailing();

   //Wait for the new Bar in a chart.
	if (LastBars == Bars) return;
	else LastBars = Bars;
	
   
   CheckCross();
}

//+------------------------------------------------------------------+
//| Check for cross and open/close the positions respectively        |
//+------------------------------------------------------------------+
void CheckCross()
{
   double h1 = iCustom(NULL, 0, "Ultra-Signal", 0, 1);
   double l1 = iCustom(NULL, 0, "Ultra-Signal", 1, 1);
   
   if (PrevCross == 0) //Was undefined
   {
      if ((h1) >= MinDiff * Poin) PrevCross = 1; //Bullish state
      else if ((l1) >= MinDiff * Poin) PrevCross = -1; //Bearish state
      return;
   }
   else if (PrevCross == 1) //Was bullish
   {
      if ((l1) >= MinDiff * Poin) //Became bearish
      {
         ClosePrev();
         fSell();
         PrevCross = -1;
      }
   }
   else if (PrevCross == -1) //Was bearish
   {
      if ((h1) >= MinDiff * Poin) //Became bullish
      {
         ClosePrev();
         fBuy();
         PrevCross = 1;
      }
   }
}

//+------------------------------------------------------------------+
//| Close previous position                                          |
//+------------------------------------------------------------------+
void ClosePrev()
{
   int total = OrdersTotal();
   for (int i = 0; i < total; i++)
   {
      if (OrderSelect(i, SELECT_BY_POS) == false) continue;
      if ((OrderSymbol() == Symbol()) && (OrderMagicNumber() == Magic))
      {
         if (OrderType() == OP_BUY)
         {
            RefreshRates();
            OrderClose(OrderTicket(), OrderLots(), Bid, Deviation);
         }
         else if (OrderType() == OP_SELL)
         {
            RefreshRates();
            OrderClose(OrderTicket(), OrderLots(), Ask, Deviation);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Sell                                                             |
//+------------------------------------------------------------------+
int fSell()
{
	double SL = 0, TP = 0;
	RefreshRates();

	if (!ECN_Mode)
	{
      if (StopLoss > 0) SL = Bid + StopLoss * Poin;
      if (TakeProfit > 0) TP = Bid - TakeProfit * Poin;
   }
	int result = OrderSend(Symbol(), OP_SELL, LotsOptimized(), Bid, Deviation, SL, TP, "Ultra-Signal", Magic);

	if (result == -1)
	{
		int e = GetLastError();
		Print(e);
	}
	else
	{
      if (ECN_Mode)
      {
      	RefreshRates();
         OrderSelect(result, SELECT_BY_TICKET);
         if (StopLoss > 0) SL = OrderOpenPrice() + StopLoss * Poin;
         if (TakeProfit > 0) TP = OrderOpenPrice() - TakeProfit * Poin;
         if ((SL != 0) || (TP != 0)) OrderModify(result, OrderOpenPrice(), SL, TP, 0);
      }
      return(result);
	}
	return(-1);
}

//+------------------------------------------------------------------+
//| Buy                                                              |
//+------------------------------------------------------------------+
int fBuy()
{
	double SL = 0, TP = 0;
	RefreshRates();

	if (!ECN_Mode)
	{
      if (StopLoss > 0) SL = Ask - StopLoss * Poin;
      if (TakeProfit > 0) TP = Ask + TakeProfit * Poin;
   }
	int result = OrderSend(Symbol(), OP_BUY, LotsOptimized(), Ask, Deviation, SL, TP, "Adjustable MA 3G", Magic);
	
	if (result == -1)
	{
		int e = GetLastError();
		Print(e);
	}
	else
	{
      if (ECN_Mode)
      {
      	RefreshRates();
         OrderSelect(result, SELECT_BY_TICKET);
         if (StopLoss > 0) SL = OrderOpenPrice() - StopLoss * Poin;
         if (TakeProfit > 0) TP = OrderOpenPrice() + TakeProfit * Poin;
         if ((SL != 0) && (TP != 0) && ((StopLoss > 0) || (TakeProfit > 0))) OrderModify(result, OrderOpenPrice(), SL, TP, 0);
      }
      return(result);
   }
	return(-1);
}

void DoTrailing()
{
   int total = OrdersTotal();
   for (int pos = 0; pos < total; pos++)
   {
      if (OrderSelect(pos, SELECT_BY_POS) == false) continue;
      if ((OrderMagicNumber() == Magic) && (OrderSymbol() == Symbol()))
      {
         if (OrderType() == OP_BUY)
         {
            RefreshRates();
            if (Bid - OrderOpenPrice() >= TrailingStop * Poin) //If profit is greater or equal to the desired Trailing Stop value
            {
               if (OrderStopLoss() < (Bid - TrailingStop * Poin)) //If the current stop-loss is below the desired trailing stop level
                  OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStop * Poin, OrderTakeProfit(), 0);
            }
         }
         else if (OrderType() == OP_SELL)
         {
            RefreshRates();
            if (OrderOpenPrice() - Ask >= TrailingStop * Poin) //If profit is greater or equal to the desired Trailing Stop value
            {
               if (OrderStopLoss() > (Ask + TrailingStop * Poin)) //If the current stop-loss is below the desired trailing stop level
                  OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TrailingStop * Poin, OrderTakeProfit(), 0);
            }
         }
      }
   }   
}

double LotsOptimized()
{
   if (!UseMM) return(Lots);
   double vol = NormalizeDouble((AccountFreeMargin() / 10000) * LotsPer10000, 1);
   if (vol <= 0) return(0.1);
   return(vol);
}

//+------------------------------------------------------------------+