//+------------------------------------------------------------------+
//|                                            EACenterOfGravity.mq4 |
//|                                                            v0.19 |
//|                                           http://www.edlogic.com |
//+------------------------------------------------------------------+
#property copyright "test 1 2 3"
#property link      "link 1 2 3"
#define COGMAGIC  706706706
#define SOFOP           0 // STANDARD_OFFSETS_FROM_OPEN_PRICE
#define OCPSASOC        1 // OUTER_COG_PLUS_SPREAD_AND_SPAN_OFF_CENTER
#define OCPSLASOCPTP    2 // OUTER_COG_PLUS_STOP_LOSS_AND_SPAN_OFF_CENTER_PLUS_TAKE_PROFIT
#define FSPSLOCASOCPTP  3 // FULL_SPAN_PLUS_STOP_LOSS_OFF_CENTER_AND_SPAN_OFF_CENTER_PLUS_TAKE_PROFIT
#define MAXUSLTPS       3 // MAX_USE_STOP_LOSS_TAKE_PROFIT_SCHEMES - reset to 0 if set too high or too low


extern int stopLoss = 111;
extern int breakEvenSteps = 77;
extern double maxLots = 0.10;
extern double lotSize = 0.10;
extern int riskPercent = 3;
extern int activateExitStrategyAtPips = -150;
extern int takeProfit = 333;
extern int maxOrders = 3;
extern double trailStopLoss = 0;
extern int useStopLossTakeProfitScheme = 2;

double Lots;
int Nmbr_Bars = 180;
double cogCenter[181],cogHigh1[181],cogHigh2[181],cogHigh3[181],cogLow3[181],cogLow2[181],cogLow1[181];
double highOrders[3], lowOrders[3], lastHighCOG[3], lastLowCOG[3];
double aboveCenterSpanPrice[3], belowCenterSpanPrice[3], aboveCenterSpanPips[3], belowCenterSpanPips[3];
double highPassingCOGprice[3], lowPassingCOGprice[3];
double bid, ask, point, cogOrderTicket;
double highLowSpanPrice, highLowSpanPips;
int digits, spread, minStopLevel;
bool alert1RunOnce = false, defeatPeriodCheck = false, defeatTrendDirectionCheck = false;
bool trendUp = false, trendDown = false, pastHalfAboveHigh[3], pastHalfBelowLow[3], continueScript;
bool testing = false;

double  originalBalance       =   0.00;
double  balance               =   0.00;
double  equity                =   0.00;
double  marginFree            =   0.00;
double  marginUsed            =   0.00;
double  marginUsedPercent     =   0.00;
double  marginUsablePercent   =   0.00;
double  profitLossPercentage  =   0.00;

int init()
{
  
  originalBalance = AccountBalance();
  continueScript = true;
  
  for (int idx = 0; idx < 3; idx++)
  {
    pastHalfAboveHigh[idx] = false;
    pastHalfBelowLow[idx] = false;
  }
  
  if (useStopLossTakeProfitScheme > MAXUSLTPS || useStopLossTakeProfitScheme < 0)
    useStopLossTakeProfitScheme = 0;
  
	return(0);
}

int deinit()
{

	return(0);
}

int start()
{
  if(Bars < 100 || IsTradeAllowed() == false)
    return;
  
  if (!continueScript)
  {
    return(0);
  }

  if (testing)
  {
    defeatPeriodCheck = true;
    defeatTrendDirectionCheck = true;
  }

  if (Period() == PERIOD_M5 || defeatPeriodCheck)
  {  
    getMarketInfo(Symbol());
    updateMoneyManager();
    checkIfHighLowOrdersClosed();
    GravityCenter2();
    calcTrend();
    setLastCOGvalues();
    calcSpans();
    ManageCurrentOrders();
    CheckToOpenOrders();
  }
  return(0);
}

void checkIfHighLowOrdersClosed()
{
  for (int idx = 0; idx < 3; idx++)
  {
    checkHighOrderClosed(idx);
    checkLowOrderClosed(idx);
  }
}

void checkHighOrderClosed(int idx)
{
  if (highOrders[idx] >= 0)
  {
    if (checkIfOrderClosed(highOrders[idx]))
    {
      highOrders[idx] = -255;
      pastHalfAboveHigh[idx] = false;
      highPassingCOGprice[idx] = 0;
    }
  }
}
 
void checkLowOrderClosed(int idx)
{
  if (lowOrders[idx] >= 0)
  {
    if (checkIfOrderClosed(lowOrders[idx]))
    {
      lowOrders[idx] = -255;
      pastHalfBelowLow[idx] = false;
      lowPassingCOGprice[idx] = 0;
    }
  }
}

bool checkIfOrderClosed(double orderNumber)
{
  int totalOrders = OrdersTotal();
  int    orderTicket;
  
  for(int idx = totalOrders - 1; idx >= 0; idx--)
	{
		if (OrderSelect(idx, SELECT_BY_POS, MODE_TRADES) && (OrderMagicNumber() == COGMAGIC || OrderSymbol() == Symbol()))
		{
			orderTicket = OrderTicket();
		
		  if (orderNumber == orderTicket)
		    return (false); // order is not closed
		}
		else { Print( "Error when order select ", GetLastError()); Sleep(1); }
	}
  
	//Alert("returning true because order not found ordernumber = ", orderNumber);
	return (true);
}


void ManageCurrentOrders()
{
  int result, error, totalOrders = OrdersTotal(), orderType;
  bool stopLossChanged = false, takeProfitChanged = false;
  double orderStopLoss, orderTakeProfit, orderOpenPrice, orderTicket;
  string orderSymbol;
  
  Sleep(1);
  
  for(int cnt = totalOrders - 1; cnt >= 0; cnt--)
  {
    Sleep(1);

    if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES) && (OrderMagicNumber() == COGMAGIC || OrderSymbol() == Symbol()))
    { 
      orderType = OrderType();
			orderSymbol = OrderSymbol();
			orderStopLoss = OrderStopLoss();
			orderTakeProfit = OrderTakeProfit();
			orderTicket = OrderTicket();
			//orderLots = OrderLots();
			orderOpenPrice = OrderOpenPrice();
      stopLossChanged = false;
      takeProfitChanged = false;
      getMarketInfo(OrderSymbol());
      
      if (orderType == OP_BUY || orderType == OP_SELL)
      { //Alert("ordertype is buy or sell = ", ordertype); Sleep(1000);
        if (orderStopLoss == 0 || orderTakeProfit == 0)
        {
          modifyStopLoss(stopLoss, takeProfit, orderType, ask, bid, point);
          Alert("stoploss was zero - stoploss takeprofit orderticket openprice = ", stopLoss, ", ", takeProfit, ", ", orderTicket, ", ", orderOpenPrice);
        } 
        else if (trailStopLoss > 0)
        {
          if (OrderType() == OP_BUY)
          {
            //orderTakeprofit = (OrderTakeProfit() - OrderOpenPrice() ) * (1 / point);
            //Alert ("orderTakeprofit = ", orderTakeprofit); Sleep(5000);
            //if (currProfit > Ask - percentStartTrailStop * takeProfit * Point)
              if (trailStopLoss * point < bid - orderOpenPrice)
              { //Alert ("trailStopLoss point bid oderopenprice - trailStopLoss * point - bid - orderOpenPrice = ",
                //trailStopLoss, ", ", DoubleToStr(point, 5), ", ",  DoubleToStr(bid, 5), ", ", DoubleToStr(orderOpenPrice, 5), ", ", DoubleToStr(trailstoploss * point, 5), ", ",  DoubleToStr(bid - orderopenprice, 5));
                if (bid - trailStopLoss * point > orderStopLoss)
                {
                  stopLossChanged = true;
                  //orderStopLoss = trailStopLoss;
                }
              }
          }
          else
          {
            //orderTakeProfit = (OrderOpenPrice() - OrderTakeProfit() ) * (1 / point);
            //Alert ("orderTakeProfit = ", orderTakeProfit); Sleep(5000);
            //if (currProfit > Bid + percentStartTrailStop * takeProfit * Point)
              if (trailStopLoss * point < orderOpenPrice - ask)
              {
                if (ask + trailStopLoss * point < orderStopLoss)
                {
                  stopLossChanged = true;
                  //orderstoploss = trailstoploss;
                }
              }
          }
      
          if (stopLossChanged || takeProfitChanged)
            modifyStopLoss(trailStopLoss, takeProfit, orderType, ask, bid, point);  
        } 
      }
    }
  }
  
	return (error);
}


int modifyStopLoss(double newstoploss, double newtakeprofit,
  int ordertype, double orderask, double orderbid, double point)
{
  double stop_loss, take_profit;
  bool   result = false, spreadmatters = false;
  int    error;
	
	//Alert("setting stoploss begin - newstoploss, newtakeprofit, ordertype, orderask, orderbid = ", newstoploss, ", ", newtakeprofit, ", ", ordertype, ", ", orderask, ", ", orderbid); Sleep(1000);
	
	if(ordertype == OP_BUY || ordertype == OP_SELL)
	{
	  //if (ordertype == OP_BUY || ordertype == OP_SELL)
	    //spreadmatters = newstoploss < spread + 10;
	  //else
	    spreadmatters = true;
	    
    //while (!result && spreadmatters)
    {
      Sleep(1);
      //Alert("orderopenprice = ", OrderOpenPrice());
      if (ordertype == OP_BUY) 
      {
        stop_loss = orderask - newstoploss * point;  
        take_profit = orderask + newtakeprofit * point;
      }
      else            
      {
        stop_loss = orderbid + newstoploss * point; 
        take_profit = orderbid - newtakeprofit * point;
      }
	
      result = OrderModify(OrderTicket(), 0, stop_loss, take_profit, 0, CLR_NONE); Sleep(1);
      //result = OrderModify(OrderTicket(), 0, stop_loss, OrderTakeProfit(), 0, CLR_NONE); Sleep(1);

      if (result != TRUE)
      {
        //error = GetLastError(); Print("stoploss Error description - number - spread - newstoploss= ", ErrorDescription(error), ", ", error, ", ", spread, ", ", newstoploss );
        //newstoploss++;
      }
    }
	}
	
  return(0);
}

void closeNonTrendingOrders(double orderType)
{
  bool   result;
  int    error;
  double price;
  int total = OrdersTotal();

  for( int cnt = total - 1; cnt >= 0; cnt-- )
  {
    if(OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES))
    {
      if(orderType == OP_BUY)
        price = bid;
      else
        price = ask;
      
      while(true)
      {
        result = OrderClose(OrderTicket(), OrderLots(), price, 3, CLR_NONE);

        if(result != TRUE) { error = GetLastError(); Print("LastError = ",error); }
          else error = 0;

        if(error == 135) RefreshRates();
        else break;
      }
    }
    else Print( "Error when order select ", GetLastError());
  }
}

void CheckToOpenOrders()  
{
  if (OrdersTotal() < maxOrders)
  {
    for (int idx = 0; idx < 3; idx++)
    {
      if (Period() == PERIOD_M5 || defeatPeriodCheck)
      {
        if (trendDown || defeatTrendDirectionCheck)
        {
          //closeNonTrendingOrders(OP_BUY);
          checkToOpenHighOrder(idx);
        }
        
        if (trendUp || defeatTrendDirectionCheck)
        {
          //closeNonTrendingOrders(OP_SELL);
          checkToOpenLowOrder(idx);
        }
      }
    }
  }
}

void checkToOpenHighOrder(int idx)
{
  getMarketInfo(Symbol());
  cogOrderTicket = -255;
  
  if (highOrders[idx] == -255)
  {
    if (bid > lastHighCOG[idx])
    {
      if (highPassingCOGprice[idx] == 0)
      {
        highPassingCOGprice[idx] = bid;
        Print("bid highPassingCOGprice[idx] idx = ", highPassingCOGprice[idx], ", ", idx);
      }
      
      if (bid > (highPassingCOGprice[idx] + aboveCenterSpanPrice[idx] / 2) && !pastHalfAboveHigh[idx])
      {
        pastHalfAboveHigh[idx] = true;
        Print("pastHalfAboveHigh[idx] idx bid > (highPassingCOGprice[idx] + aboveCenterSpanPrice[idx]= ", pastHalfAboveHigh[idx], ", ", idx, ", ", bid, ", ", highPassingCOGprice[idx], ", ", aboveCenterSpanPrice[idx]);        
      }
    }
    
    if (pastHalfAboveHigh[idx] && bid < lastHighCOG[idx])
    {
      if ((idx == 0 && highOrders[1] >= 0) || (idx == 1 && highOrders[2] >= 0) || idx == 2) // only open lower order if higher order already opened
        openSellOrder(Symbol());
    
      if (cogOrderTicket >= 0)
      {
        highOrders[idx] = cogOrderTicket;
        Alert("sell bid highPassingCOGprice[idx] idx lastHighCOG[idx] cogCenter[2] cogCenter[1] cogOrderTicket = ", bid, ", ", highPassingCOGprice[idx], ", ", idx, ", ", lastHighCOG[idx], ", ", cogCenter[2], ", ", cogCenter[1], ", ", cogOrderTicket);
      }
    }
  }
}

void checkToOpenLowOrder(int idx)
{
  getMarketInfo(Symbol());
  cogOrderTicket = -255;
  
  if (lowOrders[idx] == -255)
  {
    if (ask < lastLowCOG[idx])
    {
      if (lowPassingCOGprice[idx] == 0)
      {
        lowPassingCOGprice[idx] = ask;
        Print("ask lowPassingCOGprice[idx] idx = ", pastHalfAboveHigh[idx], ", ", idx);        
      }
      
      if (ask < (lowPassingCOGprice[idx] - belowCenterSpanPrice[idx] / 2) && !pastHalfBelowLow[idx])
      {
        pastHalfBelowLow[idx] = true;
        Print("pastHalfBelowLow[idx] idx ask < (lowPassingCOGprice[idx] - belowCenterSpanPrice[idx] = ", pastHalfAboveHigh[idx], ", ", idx, ", ", ask, ", ", lowPassingCOGprice[idx], ", ", belowCenterSpanPrice[idx]);        
      }
    }
    
    if (pastHalfBelowLow[idx] && ask > lastLowCOG[idx])
    {
      if ((idx == 2 && lowOrders[1] >= 0) || (idx == 1 && lowOrders[0] >= 0) || idx == 0) // only open higher order if lower order already opened
        openBuyOrder(Symbol());
    
      if (cogOrderTicket >= 0)
      {
        lowOrders[idx] = cogOrderTicket;
        Alert("buy ask lowPassingCOGprice[idx] idx lastLowCOG[idx] cogCenter[2] cogCenter[1] cogOrderTicket = ", ask, ", ", lowPassingCOGprice[idx], ", ", idx, ", ", lastLowCOG[idx], ", ", cogCenter[2], ", ", cogCenter[1], ", ", cogOrderTicket);
      }
    }
  }
}

bool openBuyOrder(string symbol)
{
  int buyOrderTicket = -1;
  double orderOpenPrice;
  
  while (buyOrderTicket < 0) // < 0 && OrdersTotal() < currmaxorders)
  {
    getMarketInfo(symbol);
    buyOrderTicket = OrderSend(symbol, OP_BUY, lotSize, ask, 3, 0, 0, "buyit", COGMAGIC, 0, CLR_NONE);
		
		if (buyOrderTicket < 0)
		{
			int error = GetLastError();
			// Print("buy Error = ", symbol, " ", ErrorDescription(error));
			
			if (error != 135) { return(buyOrderTicket >= 0); }
    }
  }

  if (buyOrderTicket >= 0) // && OrdersTotal() < currmaxorders)
  {  
    //lastopenedorder = "buy";
    
    if (OrderSelect(buyOrderTicket, SELECT_BY_TICKET))
    {
      orderOpenPrice = OrderOpenPrice();

      if (useStopLossTakeProfitScheme == SOFOP)
	      setStopLoss(stopLoss, takeProfit, OP_BUY, buyOrderTicket, false, orderOpenPrice); //edit here
	    else if (useStopLossTakeProfitScheme == OCPSASOC)
	      setStopLoss(lastLowCOG[0] - belowCenterSpanPrice[0] - spread * point, cogCenter[1] + aboveCenterSpanPrice[0], OP_BUY, buyOrderTicket, false, orderOpenPrice);
	    else if (useStopLossTakeProfitScheme == OCPSLASOCPTP)
        setStopLoss(lastLowCOG[0] - belowCenterSpanPrice[0] - stopLoss * point, cogCenter[1] + aboveCenterSpanPrice[0] + takeProfit * point, OP_BUY, buyOrderTicket, false, orderOpenPrice);
      else if (useStopLossTakeProfitScheme == FSPSLOCASOCPTP)
        setStopLoss(cogCenter[1] - highLowSpanPrice - stopLoss * point, cogCenter[1] + aboveCenterSpanPrice[0] + takeProfit * point, OP_BUY, buyOrderTicket, false, orderOpenPrice);

	    Alert("lastLowCOG[0]  belowCenterSpanPips[0] cogCenter[1]  aboveCenterSpanPips[0] = ", lastLowCOG[0], ", ", belowCenterSpanPips[0], ", ", cogCenter[1], ", ", aboveCenterSpanPips[0]);
	    //setStopLoss(belowCenterSpan[0] - 100 * point, takeProfit, OP_BUY, buyOrderTicket);
	    cogOrderTicket = buyOrderTicket;
	  }
	}
	
	return(buyOrderTicket < 0); // && OrdersTotal() < currmaxorders);
}

bool openSellOrder(string symbol)
{
  int sellOrderTicket = -1;
  double orderOpenPrice;
  
  while (sellOrderTicket < 0) // < 0 && OrdersTotal() < currmaxorders)
  {
    getMarketInfo(symbol);
    sellOrderTicket = OrderSend(symbol, OP_SELL, lotSize, bid, 3, 0, 0, "sellit", COGMAGIC, 0, CLR_NONE);
		
		if (sellOrderTicket < 0)
		{
			int error = GetLastError();
			//Print("sell Error = ", symbol, " ", ErrorDescription(error));
			
			if (error != 135) { return(sellOrderTicket >= 0); }
    }
  }

  if (sellOrderTicket >= 0) // && OrdersTotal() < currmaxorders)
  {  
    //lastopenedorder = "sell";
    
    if (OrderSelect(sellOrderTicket, SELECT_BY_TICKET))
    {
      orderOpenPrice = OrderOpenPrice();
    
      if (useStopLossTakeProfitScheme == SOFOP)
	      setStopLoss(stopLoss, takeProfit, OP_SELL, sellOrderTicket, false, orderOpenPrice);
	    else if (useStopLossTakeProfitScheme == OCPSASOC)
	      setStopLoss(lastHighCOG[2] + aboveCenterSpanPrice[2] + spread * point, cogCenter[1] - belowCenterSpanPrice[2], OP_SELL, sellOrderTicket, false, orderOpenPrice);
	    else if (useStopLossTakeProfitScheme == OCPSLASOCPTP)
	      setStopLoss(lastHighCOG[2] + aboveCenterSpanPrice[2] + stopLoss * point, cogCenter[1] - belowCenterSpanPrice[2] - takeProfit * point, OP_SELL, sellOrderTicket, false, orderOpenPrice);
	    else if (useStopLossTakeProfitScheme == FSPSLOCASOCPTP)
	      setStopLoss(cogCenter[1] + highLowSpanPrice + stopLoss * point, cogCenter[1] - belowCenterSpanPrice[2] - takeProfit * point, OP_SELL, sellOrderTicket, false, orderOpenPrice);

	    Alert("lastHighCOG[2]  aboveCenterSpanPips[2])  (cogCenter[1]  belowCenterSpanPips[2] = ", lastHighCOG[2], ", ", aboveCenterSpanPips[2], ", ", cogCenter[1], ", ", belowCenterSpanPips[2]);
	    //setStopLoss(aboveCenterSpan[2] + 100 * point, takeProfit, OP_SELL, sellOrderTicket);
	    cogOrderTicket = sellOrderTicket;
	  }
	}

	return(sellOrderTicket < 0); // && OrdersTotal() < currmaxorders);
}

int setStopLoss(double newStopLoss, double newTakeProfit, int orderType, int orderTicket, bool usingPips, double orderOpenPrice)
{
  double stop_loss, take_profit;
  bool   result = false;
  int    error;
  
  Alert("newstoploss, newtakeprofit = ", newStopLoss, ", ", newTakeProfit);
	//Print ("start stoploss - symbol newstoploss newtakeprofit bid ask = ", symbol, " ", newstoploss, " ", newtakeprofit, " ", bid, " ", ask);

  if (orderTicket > -1)
  {
    if(orderType == OP_BUY || orderType == OP_SELL)
    {
      while (result == false)
      {
        if (usingPips) // set pip offset from current price - otherwize absolute price is used
        {
          if (orderType == OP_BUY) 
          {
            stop_loss = ask - newStopLoss * point;  
            take_profit = ask + newTakeProfit * point;
          }
          else            
          {
            stop_loss = bid + newStopLoss * point; 
            take_profit = bid - newTakeProfit * point;
          }
        }
        else
        {
          stop_loss = newStopLoss;
          take_profit = newTakeProfit;
        }

        //result = OrderModify(orderTicket, OrderOpenPrice(), stop_loss, take_profit, 0, CLR_NONE); Sleep(1);
        result = OrderModify(orderTicket, orderOpenPrice, stop_loss, take_profit, 0, CLR_NONE); Sleep(1);

        if (result != TRUE)
        {
          Alert("stoploss error orderTicket, orderOpenPrice, stop_loss, take_profit = ", orderTicket, ", ", orderOpenPrice, ", ", stop_loss, ", ", take_profit);
          //continueScript = false;
          // error = GetLastError(); Print("ticket descrip errnum spread newstoploss newtakeprofit bid ask stop_loss take_profit minstoplevel = ", orderticket, " ", ErrorDescription(error), " ", error, " ", spread, " ", newstoploss, " ", newtakeprofit, " ", bid, " ", ask, " ", stop_loss, " ", take_profit, " ", minStopLevel);
          return(0);
        }
      }
    }
  }
  else
    Print ("stoploss ticket bad < 0 = ", orderTicket);
  	
  return(0);
}

void GravityCenter2()
{
  //int Nmbr_Bars = 3;
  int Order = 3;
  double Ecart = 1.61803399;

  double gda_120[20][20],gda_124[20],gda_128[20],gda_132[20];
  int gi_136,gi_140,gi_144,gi_148,gi_152,gi_156,gi_160;
  double gd_164,gd_172,gd_180,gd_188,gd_196;
  datetime l_time_0 = 0;

  gi_152 = Order + 1;
  gda_124[1] = Nmbr_Bars + 1;
  for (gi_160 = 1; gi_160 <= gi_152 << 1 - 2; gi_160++) {
    gd_164 = 0;
    for (gi_156 = 0; gi_156 <= Nmbr_Bars; gi_156++) gd_164 += MathPow(gi_156, gi_160);
    gda_124[gi_160 + 1] = gd_164;
  }
  for (gi_160 = 1; gi_160 <= gi_152; gi_160++) {
    gd_164 = 0;
    for (gi_156 = 0; gi_156 <= Nmbr_Bars; gi_156++) {
       if (gi_160 == 1) gd_164 += (High[gi_156] + Low[gi_156]) / 2.0;
       else gd_164 += (High[gi_156] + Low[gi_156]) / 2.0 * MathPow(gi_156, gi_160 - 1);
    }
    gda_128[gi_160] = gd_164;
  }
  for (gi_140 = 1; gi_140 <= gi_152; gi_140++) {
    for (gi_136 = 1; gi_136 <= gi_152; gi_136++) {
       gi_144 = gi_136 + gi_140 - 1;
       gda_120[gi_136][gi_140] = gda_124[gi_144];
    }
  }
  for (gi_144 = 1; gi_144 <= gi_152 - 1; gi_144++) {
    gi_148 = 0;
    gd_188 = 0;
    for (gi_136 = gi_144; gi_136 <= gi_152; gi_136++) {
       if (MathAbs(gda_120[gi_136][gi_144]) > gd_188) {
          gd_188 = MathAbs(gda_120[gi_136][gi_144]);
          gi_148 = gi_136;
       }
    }
    if (gi_148 == 0) return (0);
    if (gi_148 != gi_144) {
       for (gi_140 = 1; gi_140 <= gi_152; gi_140++) {
          gd_196 = gda_120[gi_144][gi_140];
          gda_120[gi_144][gi_140] = gda_120[gi_148][gi_140];
          gda_120[gi_148][gi_140] = gd_196;
       }
       gd_196 = gda_128[gi_144];
       gda_128[gi_144] = gda_128[gi_148];
       gda_128[gi_148] = gd_196;
    }
    for (gi_136 = gi_144 + 1; gi_136 <= gi_152; gi_136++) {
       gd_180 = gda_120[gi_136][gi_144] / gda_120[gi_144][gi_144];
       for (gi_140 = 1; gi_140 <= gi_152; gi_140++) {
          if (gi_140 == gi_144) gda_120[gi_136][gi_140] = 0;
          else gda_120[gi_136][gi_140] = gda_120[gi_136][gi_140] - gd_180 * gda_120[gi_144][gi_140];
       }
       gda_128[gi_136] = gda_128[gi_136] - gd_180 * gda_128[gi_144];
    }
  }
  gda_132[gi_152] = gda_128[gi_152] / gda_120[gi_152][gi_152];
  for (gi_136 = gi_152 - 1; gi_136 >= 1; gi_136--) {
    gd_196 = 0;
    for (gi_140 = 1; gi_140 <= gi_152 - gi_136; gi_140++) {
       gd_196 += (gda_120[gi_136][gi_136 + gi_140]) * (gda_132[gi_136 + gi_140]);
       gda_132[gi_136] = 1 / gda_120[gi_136][gi_136] * (gda_128[gi_136] - gd_196);
    }
  }
  for (gi_156 = 0; gi_156 <= Nmbr_Bars; gi_156++) {
    gd_164 = 0;
    for (gi_144 = 1; gi_144 <= Order; gi_144++) gd_164 += (gda_132[gi_144 + 1]) * MathPow(gi_156, gi_144);
    cogCenter[gi_156] = gda_132[1] + gd_164;
  }
  gd_172 = iStdDev(NULL, 0, Nmbr_Bars, 0, MODE_SMA, PRICE_HIGH, 0) * Ecart;
  for (gi_156 = 0; gi_156 <= Nmbr_Bars; gi_156++) {
    cogHigh3[gi_156] = cogCenter[gi_156] + gd_172;
    cogHigh2[gi_156] = cogCenter[gi_156] + (cogHigh3[gi_156] - cogCenter[gi_156]) / 1.382;
    cogHigh1[gi_156] = cogCenter[gi_156] + (cogHigh2[gi_156] - cogCenter[gi_156]) / 1.618;
    cogLow1[gi_156] = cogCenter[gi_156] - gd_172;
    cogLow2[gi_156] = cogCenter[gi_156] - (cogCenter[gi_156] - cogLow1[gi_156]) / 1.382;
    cogLow3[gi_156] = cogCenter[gi_156] - (cogCenter[gi_156] - cogLow2[gi_156]) / 1.618;
  }
} 

void calcTrend()
{
  trendDown = cogCenter[2] > cogCenter[1];
  trendUp = cogCenter[2] < cogCenter[1];
}

void setLastCOGvalues()
{
  lastHighCOG[0] = cogHigh1[1];
  lastHighCOG[1] = cogHigh2[1];
  lastHighCOG[2] = cogHigh3[1];
  lastLowCOG[0] = cogLow1[1];
  lastLowCOG[1] = cogLow2[1];
  lastLowCOG[2] = cogLow3[1];
}

void calcSpans()
{
  highLowSpanPrice = lastHighCOG[2] - lastLowCOG[0];
  highLowSpanPips = highLowSpanPips / point;
  
  aboveCenterSpanPrice[2] = lastHighCOG[2] - lastHighCOG[1];
  aboveCenterSpanPrice[1] = lastHighCOG[1] - lastHighCOG[0];
  aboveCenterSpanPrice[0] = cogHigh1[1] - cogCenter[1];
  
  belowCenterSpanPrice[2] = lastLowCOG[2] - lastLowCOG[1];
  belowCenterSpanPrice[1] = lastLowCOG[1] - lastLowCOG[0];
  belowCenterSpanPrice[0] = cogCenter[1] - cogLow3[1];

  aboveCenterSpanPips[2] = aboveCenterSpanPrice[2] / point;
  aboveCenterSpanPips[1] = aboveCenterSpanPrice[1] / point;
  aboveCenterSpanPips[0] = aboveCenterSpanPrice[0] / point;
  
  belowCenterSpanPips[2] = belowCenterSpanPrice[2] / point;
  belowCenterSpanPips[1] = belowCenterSpanPrice[1] / point;
  belowCenterSpanPips[0] = belowCenterSpanPrice[0] / point;
  
  
  if (!alert1RunOnce)
  {
    Print("gc point bid cogHigh3[1] cogHigh2[1] cogHigh1[1] cogCenter[2] cogCenter[1] = ",point, ", ", bid, ", ", cogHigh3[1], ", ", cogHigh2[1], ", ", cogHigh1[1], ", ", cogCenter[2], ", ", cogCenter[1]);
    Print("gc ask cogLow3[1] cogLow2[1] cogLow1[1] cogCenter[2] cogCenter[1] = ", ask, ", ", cogLow3[1], ", ", cogLow2[1], ", ", cogLow1[1], ", ", cogCenter[2], ", ", cogCenter[1]);
    Print("price cogHighLowSpan, cogHigh3High2Span, cogHigh2High1Span, cogLow3Low2Span, cogLow2Low1Span, cogHigh1Center, cogLow3Center = ", highLowSpanPrice, ", ", aboveCenterSpanPrice[2], ", ", aboveCenterSpanPrice[1], ", ", belowCenterSpanPrice[2], ", ", aboveCenterSpanPrice[1], ", ", aboveCenterSpanPrice[0], ", ", aboveCenterSpanPrice[0]);
    Print("pips cogHighLowSpan, cogHigh3High2Span, cogHigh2High1Span, cogLow3Low2Span, cogLow2Low1Span, cogHigh1Center, cogLow3Center = ", highLowSpanPips, ", ", aboveCenterSpanPips[2], ", ", aboveCenterSpanPips[1], ", ", aboveCenterSpanPips[2], ", ", aboveCenterSpanPips[1], ", ", aboveCenterSpanPips[0], ", ", aboveCenterSpanPips[0]);
    alert1RunOnce = true;
  }
}

void getMarketInfo(string symbol)
{
  RefreshRates();
  //bid = MarketInfo(symbol, MODE_BID);
  //ask = MarketInfo(symbol, MODE_ASK);
  //point = MarketInfo(symbol, MODE_POINT);
  //Alert ("point = ", point); Sleep(5000); return (0);
  digits = MarketInfo(symbol, MODE_DIGITS);
  spread = MarketInfo(symbol, MODE_SPREAD);
  minStopLevel = MarketInfo(symbol, MODE_STOPLEVEL);
  //Alert("min stop level = ", minstoplevel); Sleep(1000);
  //Alert("spread = ", spread); return (0); Sleep(1000);
  bid = NormalizeDouble(MarketInfo(symbol, MODE_BID), digits);
  ask = NormalizeDouble(MarketInfo(symbol, MODE_ASK), digits);
  point = NormalizeDouble(MarketInfo(symbol, MODE_POINT), digits);
  //Print("bid ask point = ", bid, ", ", ask, ", ", point); Sleep(10000);
}  
  
/**
 * Recalculates current free, used margin and other values
 */
double updateMoneyManager()
{
   balance = AccountBalance();
   equity = AccountEquity();
   
   marginFree = AccountFreeMargin();
   marginUsed = equity - marginFree;
   
   marginUsedPercent = marginUsed / equity * 100;
   marginUsablePercent = marginFree / equity * 100;
   
   profitLossPercentage = AccountProfit() / balance * 100;
   
   //if (balance - originalBalance > 200 || originalBalance - balance > 100)
    //continueScript = false;
}  