//+------------------------------------------------------------------+
//|                                             Basket14_03-Skoda_02 |
//+------------------------------------------------------------------+
/*
Use individual percentage deviation from linear regression
calculations to try to increase the frequency with which we get to
profit without trimming and reversing.

Attach to any chart, any timeframe. Do not attach to more than one
chart.

These are the pairs we trade:

For InterbankFX
---------------
Group 1
1.  GBPUSD
2.  EURGBP
3.  GBPJPY
4.  USDCHF
5.  NZDUSD
6.  AUDJPY
7.  EURJPY

Group 2
8.  EURUSD
9.  USDJPY
10. AUDUSD
11. NZDJPY
12. GBPCHF
13. CHFJPY
14. EURCHF

Initially, buy all pairs with negative deviation and sell all pairs
with positive deviation.

When 3 or more losing pairs have risen/fallen above/below their 24-hour highs/lows,
trim every biggest loser that rises/falls above/below the 24-hour high/low
for that currency pair, and place a trade in the opposite direction.

Close all when current equity exceeds 1% of last flat equity.

*/

//+------------------------------------------------------------------+
//|              External Variables                                  |
//+------------------------------------------------------------------+

extern bool   Bailout = false;

extern int    Slippage         =       3;
extern int    MiniSize         =   10000;
extern int    StdSize          =  100000;
extern int    MaxTrades        =      14;
extern int    ExceedenceTrigger =      3;

extern bool   UserTradingAllowed   = true;
extern bool   StopAfterNoTrades    = false;
extern bool   UseSmallestLot       = false;

extern double MaxMarginToUse      =     1.0; // Maximum percent of margin to commit to trades.
extern double Lots                =     0.1;
extern double ProfitPct           =     1.0;
extern double MaxMiniProfit       =  1000.0;
extern double MaxStdProfit        = 10000.0;

extern int    MagicNumber         =  777111;

extern int    RegressionLength    =      10; // Number of 15Min periods to use for percentage deviation calculation.


//+------------------------------------------------------------------+
//|              Internal Variables                                  |
//+------------------------------------------------------------------+

int i;
int Leverage;
int NumBuys, NumSells;
int TotalTrades;
int AccountTypeVal;

int GBPUSDbuys, GBPUSDsells;
int EURGBPbuys, EURGBPsells;
int GBPJPYbuys, GBPJPYsells;
int USDCHFbuys, USDCHFsells;
int NZDUSDbuys, NZDUSDsells;
int AUDJPYbuys, AUDJPYsells;
int EURJPYbuys, EURJPYsells;

int EURUSDbuys, EURUSDsells;
int USDJPYbuys, USDJPYsells;
int AUDUSDbuys, AUDUSDsells;
int NZDJPYbuys, NZDJPYsells;
int GBPCHFbuys, GBPCHFsells;
int CHFJPYbuys, CHFJPYsells;
int EURCHFbuys, EURCHFsells;

bool   AccountIsMini;
bool   CloseNextLoser;
bool   CloseAll;
bool   BidsHaveChanged = false;
bool   Group1LongGroup2Short, Group1ShortGroup2Long;

string AccountTypeString;
string LastFlatBal;           double valLastFlatBal;
string LastFlatEq;            double valLastFlatEq;
string LowestMarginLevel;     double valLowestMarginLevel;
string LargestFloatingLoss;   double valLargestFloatingLoss;
string MaxFloatingDrawdown;   double valMaxFloatingDrawdown;

string GBPUSDsym;
string EURGBPsym;
string GBPJPYsym;
string USDCHFsym;
string NZDUSDsym;
string AUDJPYsym;
string EURJPYsym;

string EURUSDsym;
string USDJPYsym;
string AUDUSDsym;
string NZDJPYsym;
string GBPCHFsym;
string CHFJPYsym;
string EURCHFsym;

string CommentString;

double MaxLots;
double MinLots;
double UseLots, TotalLots, BuyLots, SellLots;
double PairOverallPL, EAPL, BuyPL, SellPL, EquityExit;
double PercentMarginLevel;
double DollarProfitTarget;
double MaxMarginVar;
double Investment;

double GBPUSDPL;
double EURGBPPL;
double GBPJPYPL;
double USDCHFPL;
double NZDUSDPL;
double AUDJPYPL;
double EURJPYPL;

double EURUSDPL;
double USDJPYPL;
double AUDUSDPL;
double NZDJPYPL;
double GBPCHFPL;
double CHFJPYPL;
double EURCHFPL;

double GBPUSD_Deviation;
double EURGBP_Deviation;
double GBPJPY_Deviation;
double USDCHF_Deviation;
double NZDUSD_Deviation;
double AUDJPY_Deviation;
double EURJPY_Deviation;
double Group1_Deviation;

double EURUSD_Deviation;
double USDJPY_Deviation;
double AUDUSD_Deviation;
double NZDJPY_Deviation;
double GBPCHF_Deviation;
double CHFJPY_Deviation;
double EURCHF_Deviation;
double Group2_Deviation;

double prevGBPUSDbid = 0.0;
double prevEURGBPbid = 0.0;
double prevGBPJPYbid = 0.0;
double prevUSDCHFbid = 0.0;
double prevNZDUSDbid = 0.0;
double prevAUDJPYbid = 0.0;
double prevEURJPYbid = 0.0;

double prevEURUSDbid = 0.0;
double prevUSDJPYbid = 0.0;
double prevAUDUSDbid = 0.0;
double prevNZDJPYbid = 0.0;
double prevGBPCHFbid = 0.0;
double prevCHFJPYbid = 0.0;
double prevEURCHFbid = 0.0;

double BiggestWinnerPL;
double BiggestWinnerLots;
int    BiggestWinnerTicket;
string BiggestWinnerType;
string BiggestWinnerSymbol;
double BiggestWinnerPlusBiggestLoser;

double BiggestLoserPL;
double BiggestLoserLots;
int    BiggestLoserTicket;
string BiggestLoserType;
string BiggestLoserSymbol;

//+------------------------------------------------------------------+
//|   Expert Advisor Initialization, executes only when the EA is    |
//|   first attached to a chart or on platform  restart.             |
//+------------------------------------------------------------------+

int init()
{
  SetGlobalVariableNames();
  InitGlobalVars();

  return (0);
}

//+------------------------------------------------------------------+
//|    Expert Advisor start function, executes on each tick of the   |
//|    currecy pair it's attached to.                                |
//+------------------------------------------------------------------+

int start()
{
  if (Bailout || (!IsTesting() && !IsExpertEnabled()))
  {
    Comment("Expert is not enabled");

    return(0);
  }

  RefreshGlobalVars();
  GetAccountInfo();  
  SetSymbols();
  SetAccountType();
  SetLotSize();  
  Count_PL_Trades_Lots();
  SetExitTargets();

  BidsHaveChanged = 

    prevGBPUSDbid != 0.0 &&
    prevEURGBPbid != 0.0 &&
    prevGBPJPYbid != 0.0 &&
    prevUSDCHFbid != 0.0 &&
    prevNZDUSDbid != 0.0 &&
    prevAUDJPYbid != 0.0 &&
    prevEURJPYbid != 0.0 &&

    prevEURUSDbid != 0.0 &&
    prevUSDJPYbid != 0.0 &&
    prevAUDUSDbid != 0.0 &&
    prevNZDJPYbid != 0.0 &&
    prevGBPCHFbid != 0.0 &&
    prevCHFJPYbid != 0.0 &&
    prevEURCHFbid != 0.0 &&

    (prevGBPUSDbid != MarketInfo(GBPUSDsym, MODE_BID) ||
     prevEURGBPbid != MarketInfo(EURGBPsym, MODE_BID) ||
     prevGBPJPYbid != MarketInfo(GBPJPYsym, MODE_BID) ||
     prevUSDCHFbid != MarketInfo(USDCHFsym, MODE_BID) ||
     prevNZDUSDbid != MarketInfo(NZDUSDsym, MODE_BID) ||
     prevAUDJPYbid != MarketInfo(AUDJPYsym, MODE_BID) ||
     prevEURJPYbid != MarketInfo(EURJPYsym, MODE_BID) ||
     prevEURUSDbid != MarketInfo(EURUSDsym, MODE_BID) ||
     prevUSDJPYbid != MarketInfo(USDJPYsym, MODE_BID) ||
     prevAUDUSDbid != MarketInfo(AUDUSDsym, MODE_BID) ||
     prevNZDJPYbid != MarketInfo(NZDJPYsym, MODE_BID) ||
     prevGBPCHFbid != MarketInfo(GBPCHFsym, MODE_BID) ||
     prevCHFJPYbid != MarketInfo(CHFJPYsym, MODE_BID) ||
     prevEURCHFbid != MarketInfo(EURCHFsym, MODE_BID));

  CloseAllTradesIfNeeded();
  TrimIfNeeded();
  DetermineBias();

  if (TotalTrades == 0)
  {
    if (AccountBalance() > valLastFlatBal)
    {
      valLastFlatBal = AccountBalance();
      GlobalVariableSet(LastFlatBal, valLastFlatBal);
    }

    if (AccountEquity() > valLastFlatEq)
    {
      valLastFlatEq = AccountEquity();
      GlobalVariableSet(LastFlatEq,  valLastFlatEq);
    }

    if (!IsExpertEnabled() || StopAfterNoTrades) return(0);

    CloseAll = false;
  }

  if (!CloseAll && valLastFlatEq != 0.0 && AccountEquity()-valLastFlatEq > DollarProfitTarget)
  {
    CloseAll = true; 
    return(0);
  }

  OpenTradesIfNeeded();
  ExamineMarginAndFloat();

  prevGBPUSDbid = MarketInfo(GBPUSDsym, MODE_BID);
  prevEURGBPbid = MarketInfo(EURGBPsym, MODE_BID);
  prevGBPJPYbid = MarketInfo(GBPJPYsym, MODE_BID);
  prevUSDCHFbid = MarketInfo(USDCHFsym, MODE_BID);
  prevNZDUSDbid = MarketInfo(NZDUSDsym, MODE_BID);
  prevAUDJPYbid = MarketInfo(AUDJPYsym, MODE_BID);
  prevEURJPYbid = MarketInfo(EURJPYsym, MODE_BID);

  prevEURUSDbid = MarketInfo(EURUSDsym, MODE_BID);
  prevUSDJPYbid = MarketInfo(USDJPYsym, MODE_BID);
  prevAUDUSDbid = MarketInfo(AUDUSDsym, MODE_BID);
  prevNZDJPYbid = MarketInfo(NZDJPYsym, MODE_BID);
  prevGBPCHFbid = MarketInfo(GBPCHFsym, MODE_BID);
  prevCHFJPYbid = MarketInfo(CHFJPYsym, MODE_BID);
  prevEURCHFbid = MarketInfo(EURCHFsym, MODE_BID);

  PrintChartComments();
    
  return(0);
}

//+------------------------------------------------------------------+
//|          Assign values to global variable namestrings.           |
//+------------------------------------------------------------------+

void SetGlobalVariableNames()
{
  LowestMarginLevel = MagicNumber+"_LowestMarginLevel";
  LargestFloatingLoss = MagicNumber+"_LargestFloatingLoss";
  MaxFloatingDrawdown = MagicNumber+"_MaxFloatingDrawdown";

  LastFlatBal = MagicNumber+"_LastFlatBal";
  LastFlatEq  = MagicNumber+"_LastFlatEq";

  return(0);
}

//+------------------------------------------------------------------+
//|            Assign initial values to global variables.            |
//+------------------------------------------------------------------+

void InitGlobalVars()
{
  if (!GlobalVariableCheck(LowestMarginLevel)) GlobalVariableSet(LowestMarginLevel, 100000000.0);
  if (!GlobalVariableCheck(LargestFloatingLoss)) GlobalVariableSet(LargestFloatingLoss, 0.0);
  if (!GlobalVariableCheck(MaxFloatingDrawdown)) GlobalVariableSet(MaxFloatingDrawdown, 0.0);

  if (!GlobalVariableCheck(LastFlatBal)) GlobalVariableSet(LastFlatBal, AccountBalance());
  if (!GlobalVariableCheck(LastFlatEq)) GlobalVariableSet(LastFlatEq, AccountEquity());

  return(0);
}

//+------------------------------------------------------------------+
//|   Get global variable values via their namestring and assign the |
//|   stored values to the variables used in the EA's logic.         |
//+------------------------------------------------------------------+

void RefreshGlobalVars()
{
  valLowestMarginLevel = GlobalVariableGet(LowestMarginLevel);
  valLargestFloatingLoss = GlobalVariableGet(LargestFloatingLoss);
  valMaxFloatingDrawdown = GlobalVariableGet(MaxFloatingDrawdown);

  valLastFlatBal = GlobalVariableGet(LastFlatBal);
  valLastFlatEq  = GlobalVariableGet(LastFlatEq);

  return(0);
}

//+------------------------------------------------------------------+
//|  Get important account parameters that affect how the lot size   |
//|  will be set.                                                    |
//+------------------------------------------------------------------+

void GetAccountInfo()
{
  // Get account leverage, account type.
  Leverage       = AccountLeverage();

  AccountTypeVal = MarketInfo(Symbol(), MODE_LOTSIZE);
  MaxLots        = MarketInfo(Symbol(), MODE_MAXLOT);
  MinLots        = MarketInfo(Symbol(), MODE_MINLOT);

  return(0);
}

//+------------------------------------------------------------------+
//|                 Set the traded symbol strings.                   |
//+------------------------------------------------------------------+

void SetSymbols()
{
  string AddMangle = "";
  if (StringLen(Symbol()) > 6) AddMangle = StringSubstr(Symbol(), 6);

  GBPUSDsym = "GBPUSD" + AddMangle;
  EURGBPsym = "EURGBP" + AddMangle;
  GBPJPYsym = "GBPJPY" + AddMangle;
  USDCHFsym = "USDCHF" + AddMangle;
  NZDUSDsym = "NZDUSD" + AddMangle;
  AUDJPYsym = "AUDJPY" + AddMangle;
  EURJPYsym = "EURJPY" + AddMangle;

  EURUSDsym = "EURUSD" + AddMangle;
  USDJPYsym = "USDJPY" + AddMangle;
  AUDUSDsym = "AUDUSD" + AddMangle;
  NZDJPYsym = "NZDJPY" + AddMangle;
  GBPCHFsym = "GBPCHF" + AddMangle;
  CHFJPYsym = "CHFJPY" + AddMangle;
  EURCHFsym = "EURCHF" + AddMangle;

  return(0);
}

//+------------------------------------------------------------------+
//|             Set the account type and minimum equity.             |
//+------------------------------------------------------------------+

void SetAccountType()
{
  if (AccountTypeVal == MiniSize || StringLen(Symbol()) == 7)
  {
    AccountIsMini     = true;
    AccountTypeString = "MINI";
  }
  else if (AccountTypeVal == StdSize || StringLen(Symbol()) == 6)
  {
    AccountIsMini     = false;
    AccountTypeString = "STANDARD";
  }
  
  return(0);
}

//+------------------------------------------------------------------+
//|                 Set the lot size for any trades.                 |
//+------------------------------------------------------------------+

void SetLotSize()
{
  Investment = MaxMarginToUse / 100.0;

  // The symbol the EA is attached to should be good enough for the purposes of LOTSIZE
  UseLots = valLastFlatEq * Investment * (Leverage / MarketInfo(Symbol(), MODE_LOTSIZE));
  UseLots = StrToDouble(DoubleToStr(UseLots,2));

  if (UseSmallestLot || UseLots < MinLots) UseLots = MinLots;
  if (UseLots > MaxLots) UseLots = MaxLots;

  return(0);
}

//+------------------------------------------------------------------+
//|  Do some accounting -- count the profit/loss, the open trades,   |
//|  and the number of open lots.                                    |
//+------------------------------------------------------------------+

void Count_PL_Trades_Lots()
{
  NumBuys            =    0;
  NumSells           =    0;
  TotalTrades        =    0;
  EAPL               =    0.0;
  BuyPL              =    0.0;
  SellPL             =    0.0;
  TotalLots          =    0.0;
  BuyLots            =    0.0;
  SellLots           =    0.0;

  GBPUSDbuys = 0; GBPUSDsells = 0;
  EURGBPbuys = 0; EURGBPsells = 0;
  GBPJPYbuys = 0; GBPJPYsells = 0;
  USDCHFbuys = 0; USDCHFsells = 0;
  NZDUSDbuys = 0; NZDUSDsells = 0;
  AUDJPYbuys = 0; AUDJPYsells = 0;
  EURJPYbuys = 0; EURJPYsells = 0;

  EURUSDbuys = 0; EURUSDsells = 0;
  USDJPYbuys = 0; USDJPYsells = 0;
  AUDUSDbuys = 0; AUDUSDsells = 0;
  NZDJPYbuys = 0; NZDJPYsells = 0;
  GBPCHFbuys = 0; GBPCHFsells = 0;
  CHFJPYbuys = 0; CHFJPYsells = 0;
  EURCHFbuys = 0; EURCHFsells = 0;

  BiggestWinnerPL = 0.0;
  BiggestWinnerLots = 0.0;
  BiggestWinnerTicket = 0;
  BiggestWinnerType = "";
  BiggestWinnerSymbol = "";

  BiggestLoserPL = 0.0;
  BiggestLoserLots = 0.0;
  BiggestLoserTicket = 0;
  BiggestLoserType = "";
  BiggestLoserSymbol = "";

  for (i = 0; i < OrdersTotal(); i++)
  {
    OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

    if (OrderMagicNumber() == MagicNumber)
    {
      PairOverallPL = OrderProfit() + OrderSwap() + OrderCommission();
      EAPL  += PairOverallPL;
      TotalLots += OrderLots();

      if (OrderType() == OP_BUY)
      {
        BuyPL += PairOverallPL;

        if (PairOverallPL > BiggestWinnerPL)
        {
          BiggestWinnerPL     = PairOverallPL;
          BiggestWinnerLots   = OrderLots();
          BiggestWinnerTicket = OrderTicket();
          BiggestWinnerType   = "BUY";
          BiggestWinnerSymbol = OrderSymbol();
        }

        if (PairOverallPL < BiggestLoserPL)
        {
          BiggestLoserPL     = PairOverallPL;
          BiggestLoserLots   = OrderLots();
          BiggestLoserTicket = OrderTicket();
          BiggestLoserType   = "BUY";
          BiggestLoserSymbol = OrderSymbol();
        }

        BuyLots += OrderLots();

        NumBuys++;

        if (OrderSymbol() == GBPUSDsym) { GBPUSDbuys++; GBPUSDPL = PairOverallPL; }
        else
        if (OrderSymbol() == EURGBPsym) { EURGBPbuys++; EURGBPPL = PairOverallPL; }
        else
        if (OrderSymbol() == GBPJPYsym) { GBPJPYbuys++; GBPJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == USDCHFsym) { USDCHFbuys++; USDCHFPL = PairOverallPL; }
        else
        if (OrderSymbol() == NZDUSDsym) { NZDUSDbuys++; NZDUSDPL = PairOverallPL; }
        else
        if (OrderSymbol() == AUDJPYsym) { AUDJPYbuys++; AUDJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == EURJPYsym) { EURJPYbuys++; EURJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == EURUSDsym) { EURUSDbuys++; EURUSDPL = PairOverallPL; }
        else
        if (OrderSymbol() == USDJPYsym) { USDJPYbuys++; USDJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == AUDUSDsym) { AUDUSDbuys++; AUDUSDPL = PairOverallPL; }
        else
        if (OrderSymbol() == NZDJPYsym) { NZDJPYbuys++; NZDJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == GBPCHFsym) { GBPCHFbuys++; GBPCHFPL = PairOverallPL; }
        else
        if (OrderSymbol() == CHFJPYsym) { CHFJPYbuys++; CHFJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == EURCHFsym) { EURCHFbuys++; EURCHFPL = PairOverallPL; }
      }

      if (OrderType() == OP_SELL)
      {
        SellPL += PairOverallPL;

        if (PairOverallPL> BiggestWinnerPL)
        {
          BiggestWinnerPL     = PairOverallPL;
          BiggestWinnerLots   = OrderLots();
          BiggestWinnerTicket = OrderTicket();
          BiggestWinnerType   = "SELL";
          BiggestWinnerSymbol = OrderSymbol();
        }

        if (PairOverallPL< BiggestLoserPL)
        {
          BiggestLoserPL     = PairOverallPL;
          BiggestLoserLots   = OrderLots();
          BiggestLoserTicket = OrderTicket();
          BiggestLoserType   = "SELL";
          BiggestLoserSymbol = OrderSymbol();
        }

        SellLots += OrderLots();

        NumSells++;

        if (OrderSymbol() == GBPUSDsym) { GBPUSDsells++; GBPUSDPL = PairOverallPL; }
        else
        if (OrderSymbol() == EURGBPsym) { EURGBPsells++; EURGBPPL = PairOverallPL; }
        else
        if (OrderSymbol() == GBPJPYsym) { GBPJPYsells++; GBPJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == USDCHFsym) { USDCHFsells++; USDCHFPL = PairOverallPL; }
        else
        if (OrderSymbol() == NZDUSDsym) { NZDUSDsells++; NZDUSDPL = PairOverallPL; }
        else
        if (OrderSymbol() == AUDJPYsym) { AUDJPYsells++; AUDJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == EURJPYsym) { EURJPYsells++; EURJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == EURUSDsym) { EURUSDsells++; EURUSDPL = PairOverallPL; }
        else
        if (OrderSymbol() == USDJPYsym) { USDJPYsells++; USDJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == AUDUSDsym) { AUDUSDsells++; AUDUSDPL = PairOverallPL; }
        else
        if (OrderSymbol() == NZDJPYsym) { NZDJPYsells++; NZDJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == GBPCHFsym) { GBPCHFsells++; GBPCHFPL = PairOverallPL; }
        else
        if (OrderSymbol() == CHFJPYsym) { CHFJPYsells++; CHFJPYPL = PairOverallPL; }
        else
        if (OrderSymbol() == EURCHFsym) { EURCHFsells++; EURCHFPL = PairOverallPL; }
      }
    }
  }
  TotalTrades = NumBuys+NumSells;

  return(0);
}

//+------------------------------------------------------------------+
//|         Set the dollar profit and trim target values.            |
//+------------------------------------------------------------------+

void SetExitTargets()
{
  DollarProfitTarget = StrToDouble(DoubleToStr(valLastFlatEq*ProfitPct/100.0,2));

  if (AccountIsMini)
  {
    if (DollarProfitTarget > MaxMiniProfit) DollarProfitTarget = MaxMiniProfit;
  }
  else
  {
    if (DollarProfitTarget > MaxStdProfit) DollarProfitTarget = MaxStdProfit;
  }

  return(0);
}

//+------------------------------------------------------------------+
//|                 Close all of the open trades.                    |
//+------------------------------------------------------------------+

void CloseAllTradesIfNeeded()
{
  if (BidsHaveChanged && CloseAll)
  {
    for(i = 0; i < OrdersTotal(); i++)
    {
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

      if (OrderMagicNumber() == MagicNumber)
      {
        if (OrderType() == OP_BUY)
        {
          Comment("In full closure mode.  Closing a ", OrderSymbol(), " buy trade...");
          Print("In full closure mode.  Closing a ", OrderSymbol(), " buy trade...");
          OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(), MODE_BID),Slippage,White);
          Sleep(1000);
        }    
        else
        if (OrderType() == OP_SELL)
        {
          Comment("In full closure mode.  Closing a ", OrderSymbol(), " sell trade...");
          Print("In full closure mode.  Closing a ", OrderSymbol(), " sell trade...");
          OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(), MODE_ASK),Slippage,White);
          Sleep(1000);
        }
      }
    }
  }
  
  return(0);
}

//+------------------------------------------------------------------+
//| Count the number of pairs that have risen/fallen above/below     |
//| their 24-hour highs/lows.                                        |
//+------------------------------------------------------------------+

int ExceedenceCount()
{
  int theCount = 0;

  if (GBPUSDPL < 0.5*BiggestLoserPL &&
      MarketInfo(GBPUSDsym, MODE_BID) <= iLow(GBPUSDsym, PERIOD_H1, iLowest(GBPUSDsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(GBPUSDsym, MODE_ASK) >= iHigh(GBPUSDsym, PERIOD_H1, iHighest(GBPUSDsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (EURGBPPL < 0.5*BiggestLoserPL &&
      MarketInfo(EURGBPsym, MODE_BID) <= iLow(EURGBPsym, PERIOD_H1, iLowest(EURGBPsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(EURGBPsym, MODE_ASK) >= iHigh(EURGBPsym, PERIOD_H1, iHighest(EURGBPsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (GBPJPYPL < 0.5*BiggestLoserPL &&
      MarketInfo(GBPJPYsym, MODE_BID) <= iLow(GBPJPYsym, PERIOD_H1, iLowest(GBPJPYsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(GBPJPYsym, MODE_ASK) >= iHigh(GBPJPYsym, PERIOD_H1, iHighest(GBPJPYsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (USDCHFPL < 0.5*BiggestLoserPL &&
      MarketInfo(USDCHFsym, MODE_BID) <= iLow(USDCHFsym, PERIOD_H1, iLowest(USDCHFsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(USDCHFsym, MODE_ASK) >= iHigh(USDCHFsym, PERIOD_H1, iHighest(USDCHFsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (NZDUSDPL < 0.5*BiggestLoserPL &&
      MarketInfo(NZDUSDsym, MODE_BID) <= iLow(NZDUSDsym, PERIOD_H1, iLowest(NZDUSDsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(NZDUSDsym, MODE_ASK) >= iHigh(NZDUSDsym, PERIOD_H1, iHighest(NZDUSDsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (AUDJPYPL < 0.5*BiggestLoserPL &&
      MarketInfo(AUDJPYsym, MODE_BID) <= iLow(AUDJPYsym, PERIOD_H1, iLowest(AUDJPYsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(AUDJPYsym, MODE_ASK) >= iHigh(AUDJPYsym, PERIOD_H1, iHighest(AUDJPYsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (EURJPYPL < 0.5*BiggestLoserPL &&
      MarketInfo(EURJPYsym, MODE_BID) <= iLow(EURJPYsym, PERIOD_H1, iLowest(EURJPYsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(EURJPYsym, MODE_ASK) >= iHigh(EURJPYsym, PERIOD_H1, iHighest(EURJPYsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (EURUSDPL < 0.5*BiggestLoserPL &&
      MarketInfo( EURUSDsym, MODE_BID) <= iLow( EURUSDsym, PERIOD_H1, iLowest( EURUSDsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo( EURUSDsym, MODE_ASK) >= iHigh( EURUSDsym, PERIOD_H1, iHighest( EURUSDsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (USDJPYPL < 0.5*BiggestLoserPL &&
      MarketInfo(USDJPYsym, MODE_BID) <= iLow(USDJPYsym, PERIOD_H1, iLowest(USDJPYsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(USDJPYsym, MODE_ASK) >= iHigh(USDJPYsym, PERIOD_H1, iHighest(USDJPYsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (AUDUSDPL < 0.5*BiggestLoserPL &&
      MarketInfo(AUDUSDsym, MODE_BID) <= iLow(AUDUSDsym, PERIOD_H1, iLowest(AUDUSDsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(AUDUSDsym, MODE_ASK) >= iHigh(AUDUSDsym, PERIOD_H1, iHighest(AUDUSDsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (NZDJPYPL < 0.5*BiggestLoserPL &&
      MarketInfo(NZDJPYsym, MODE_BID) <= iLow(NZDJPYsym, PERIOD_H1, iLowest(NZDJPYsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(NZDJPYsym, MODE_ASK) >= iHigh(NZDJPYsym, PERIOD_H1, iHighest(NZDJPYsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (GBPCHFPL < 0.5*BiggestLoserPL &&
      MarketInfo(GBPCHFsym, MODE_BID) <= iLow(GBPCHFsym, PERIOD_H1, iLowest(GBPCHFsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(GBPCHFsym, MODE_ASK) >= iHigh(GBPCHFsym, PERIOD_H1, iHighest(GBPCHFsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (CHFJPYPL < 0.5*BiggestLoserPL &&
      MarketInfo(CHFJPYsym, MODE_BID) <= iLow(CHFJPYsym, PERIOD_H1, iLowest(CHFJPYsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(CHFJPYsym, MODE_ASK) >= iHigh(CHFJPYsym, PERIOD_H1, iHighest(CHFJPYsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  if (EURCHFPL < 0.5*BiggestLoserPL &&
      MarketInfo(EURCHFsym, MODE_BID) <= iLow(EURCHFsym, PERIOD_H1, iLowest(EURCHFsym, PERIOD_H1, MODE_LOW, 24, 0)) ||
      MarketInfo(EURCHFsym, MODE_ASK) >= iHigh(EURCHFsym, PERIOD_H1, iHighest(EURCHFsym, PERIOD_H1, MODE_HIGH, 24, 0)))
  {
    theCount++;
  }

  return(theCount);
}

//+------------------------------------------------------------------+
//|                     Trim a biggest loser.                        |
//+------------------------------------------------------------------+

void TrimIfNeeded()
{
  bool CloseResult;

  if (BidsHaveChanged &&
      MathAbs(BiggestLoserPL) > DollarProfitTarget &&
     !CloseAll)
  {
    for (i = 0; i < OrdersTotal(); i++)
    {
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

      if (ExceedenceCount() >= ExceedenceTrigger &&
          OrderMagicNumber() == MagicNumber      &&
          BiggestLoserTicket == OrderTicket())
      {
        if (OrderType() == OP_BUY &&
            MarketInfo(BiggestLoserSymbol, MODE_BID) <= iLow(BiggestLoserSymbol, PERIOD_H1, iLowest(BiggestLoserSymbol, PERIOD_H1, MODE_LOW, 24, 0)))
        {
          Comment("Closing a " + BiggestLoserSymbol + " biggest-loser buy trade...");
          Print("Closing a " + BiggestLoserSymbol + " biggest-loser buy trade...");
          CloseResult = OrderClose(BiggestLoserTicket,OrderLots(),MarketInfo(BiggestLoserSymbol, MODE_BID),Slippage,White);
          Sleep(1000);

          if (CloseResult) // If closure succeeded, open the same symbol as a SELL
          {
            Comment("Opening a " + BiggestLoserSymbol + " sell trade...");
            Print("Short " + BiggestLoserSymbol + ".");
            OrderSend(BiggestLoserSymbol,OP_SELL,UseLots,MarketInfo(BiggestLoserSymbol, MODE_BID),Slippage,0,0,"Biggest loser SOLD",MagicNumber,Red);
            Sleep(1000);
          }
        }
        else
        if (OrderType() == OP_SELL &&
            MarketInfo(BiggestLoserSymbol, MODE_ASK) >= iHigh(BiggestLoserSymbol, PERIOD_H1, iHighest(BiggestLoserSymbol, PERIOD_H1, MODE_HIGH, 24, 0)))
        {
          Comment("Closing a " + BiggestLoserSymbol + " biggest-loser sell trade...");
          Print("Closing a " + BiggestLoserSymbol + " biggest-loser sell trade...");
          CloseResult = OrderClose(BiggestLoserTicket,OrderLots(),MarketInfo(BiggestLoserSymbol, MODE_ASK),Slippage,White);
          Sleep(1000);

          if (CloseResult) // If closure succeeded, open the same symbol as a BUY
          {
            Comment("Opening a " + BiggestLoserSymbol + " buy trade...");
            Print("Long " + BiggestWinnerSymbol + ".");
            OrderSend(BiggestLoserSymbol,OP_BUY,UseLots,MarketInfo(BiggestLoserSymbol, MODE_ASK),Slippage,0,0,"Biggest loser BOUGHT",MagicNumber,Blue);
            Sleep(1000);
          }
        }
      }
    } 
  }

  return(0);
}

//+------------------------------------------------------------------+
//|        Determine which group to buy and which to sell.           |
//+------------------------------------------------------------------+

void DetermineBias()
{
  GBPUSD_Deviation = Deviation(GBPUSDsym, RegressionLength, 0);
  EURGBP_Deviation = Deviation(EURGBPsym, RegressionLength, 0);
  GBPJPY_Deviation = Deviation(GBPJPYsym, RegressionLength, 0);
  USDCHF_Deviation = Deviation(USDCHFsym, RegressionLength, 0);
  NZDUSD_Deviation = Deviation(NZDUSDsym, RegressionLength, 0);
  AUDJPY_Deviation = Deviation(AUDJPYsym, RegressionLength, 0);
  EURJPY_Deviation = Deviation(EURJPYsym, RegressionLength, 0);
  
  EURUSD_Deviation = Deviation(EURUSDsym, RegressionLength, 0);
  USDJPY_Deviation = Deviation(USDJPYsym, RegressionLength, 0);
  AUDUSD_Deviation = Deviation(AUDUSDsym, RegressionLength, 0);
  NZDJPY_Deviation = Deviation(NZDJPYsym, RegressionLength, 0);
  GBPCHF_Deviation = Deviation(GBPCHFsym, RegressionLength, 0);
  CHFJPY_Deviation = Deviation(CHFJPYsym, RegressionLength, 0);
  EURCHF_Deviation = Deviation(EURCHFsym, RegressionLength, 0);
  
  return(0);
}

//+------------------------------------------------------------------+
//|                         Open Trades                              |
//+------------------------------------------------------------------+

void OpenTradesIfNeeded()
{
  if (BidsHaveChanged && !CloseAll && TotalTrades < MaxTrades)
  {
          
      if (GBPUSDbuys == 0 && GBPUSDsells == 0 && GBPUSD_Deviation < 0)
      {
        Comment("Opening a GBPUSD buy trade...");
        Print("Long GBPUSD.");
        OrderSend(GBPUSDsym,OP_BUY,UseLots,MarketInfo(GBPUSDsym, MODE_ASK),Slippage,0,0,"BOUGHT GBPUSD",MagicNumber,Blue);
        Sleep(1000);
      }

      if (EURGBPbuys == 0 && EURGBPsells == 0 && EURGBP_Deviation < 0)
      {
        Comment("Opening a EURGBP buy trade...");
        Print("Long EURGBP.");
        OrderSend(EURGBPsym,OP_BUY,UseLots,MarketInfo(EURGBPsym, MODE_ASK),Slippage,0,0,"BOUGHT EURGBP",MagicNumber,Blue);
        Sleep(1000);
      }

      if (GBPJPYbuys == 0 && GBPJPYsells == 0 && GBPJPY_Deviation < 0)
      {
        Comment("Opening a GBPJPY buy trade...");
        Print("Long GBPJPY.");
        OrderSend(GBPJPYsym,OP_BUY,UseLots,MarketInfo(GBPJPYsym, MODE_ASK),Slippage,0,0,"BOUGHT GBPJPY",MagicNumber,Blue);
        Sleep(1000);
      }

      if (USDCHFbuys == 0 && USDCHFsells == 0 && USDCHF_Deviation < 0)
      {
        Comment("Opening a USDCHF buy trade...");
        Print("Long USDCHF.");
        OrderSend(USDCHFsym,OP_BUY,UseLots,MarketInfo(USDCHFsym, MODE_ASK),Slippage,0,0,"BOUGHT USDCHF",MagicNumber,Blue);
        Sleep(1000);
      }

      if (NZDUSDbuys == 0 && NZDUSDsells == 0 && NZDUSD_Deviation < 0)
      {
        Comment("Opening a NZDUSD buy trade...");
        Print("Long NZDUSD.");
        OrderSend(NZDUSDsym,OP_BUY,UseLots,MarketInfo(NZDUSDsym, MODE_ASK),Slippage,0,0,"BOUGHT NZDUSD",MagicNumber,Blue);
        Sleep(1000);
      }

      if (AUDJPYbuys == 0 && AUDJPYsells == 0 && AUDJPY_Deviation < 0)
      {
        Comment("Opening a AUDJPY buy trade...");
        Print("Long AUDJPY.");
        OrderSend(AUDJPYsym,OP_BUY,UseLots,MarketInfo(AUDJPYsym, MODE_ASK),Slippage,0,0,"BOUGHT AUDJPY",MagicNumber,Blue);
        Sleep(1000);
      }

      if (EURJPYbuys == 0 && EURJPYsells == 0 && EURJPY_Deviation < 0)
      {
        Comment("Opening a EURJPY buy trade...");
        Print("Long EURJPY.");
        OrderSend(EURJPYsym,OP_BUY,UseLots,MarketInfo(EURJPYsym, MODE_ASK),Slippage,0,0,"BOUGHT EURJPY",MagicNumber,Blue);
        Sleep(1000);
      }

      if (EURUSDsells == 0 && EURUSDbuys == 0 && EURUSD_Deviation > 0)
      {
        Comment("Opening a EURUSD sell trade...");
        Print("Short EURUSD.");
        OrderSend(EURUSDsym,OP_SELL,UseLots,MarketInfo(EURUSDsym, MODE_BID),Slippage,0,0,"SOLD EURUSD",MagicNumber,Red);
        Sleep(1000);
      }

      if (USDJPYsells == 0 && USDJPYbuys == 0 && USDJPY_Deviation > 0)
      {
        Comment("Opening a USDJPY sell trade...");
        Print("Short USDJPY.");
        OrderSend(USDJPYsym,OP_SELL,UseLots,MarketInfo(USDJPYsym, MODE_BID),Slippage,0,0,"SOLD USDJPY",MagicNumber,Red);
        Sleep(1000);
      }

      if (AUDUSDsells == 0 && AUDUSDbuys == 0 && AUDUSD_Deviation > 0)
      {
        Comment("Opening a AUDUSD sell trade...");
        Print("Short AUDUSD.");
        OrderSend(AUDUSDsym,OP_SELL,UseLots,MarketInfo(AUDUSDsym, MODE_BID),Slippage,0,0,"SOLD AUDUSD",MagicNumber,Red);
        Sleep(1000);
      }

      if (NZDJPYsells == 0 && NZDJPYbuys == 0 && NZDJPY_Deviation > 0)
      {
        Comment("Opening a NZDJPY sell trade...");
        Print("Short NZDJPY.");
        OrderSend(NZDJPYsym,OP_SELL,UseLots,MarketInfo(NZDJPYsym, MODE_BID),Slippage,0,0,"SOLD NZDJPY",MagicNumber,Red);
        Sleep(1000);
      }

      if (GBPCHFsells == 0 && GBPCHFbuys == 0 && GBPCHF_Deviation > 0)
      {
        Comment("Opening a GBPCHF sell trade...");
        Print("Short GBPCHF.");
        OrderSend(GBPCHFsym,OP_SELL,UseLots,MarketInfo(GBPCHFsym, MODE_BID),Slippage,0,0,"SOLD GBPCHF",MagicNumber,Red);
        Sleep(1000);
      }

      if (CHFJPYsells == 0 && CHFJPYbuys == 0 && CHFJPY_Deviation > 0)
      {
        Comment("Opening a CHFJPY sell trade...");
        Print("Short CHFJPY.");
        OrderSend(CHFJPYsym,OP_SELL,UseLots,MarketInfo(CHFJPYsym, MODE_BID),Slippage,0,0,"SOLD CHFJPY",MagicNumber,Red);
        Sleep(1000);
      }

      if (EURCHFsells == 0 && EURCHFbuys == 0 && EURCHF_Deviation > 0)
      {
        Comment("Opening a EURCHF sell trade...");
        Print("Short EURCHF.");
        OrderSend(EURCHFsym,OP_SELL,UseLots,MarketInfo(EURCHFsym, MODE_BID),Slippage,0,0,"SOLD EURCHF",MagicNumber,Red);
        Sleep(1000);
      }
    
          
      if (GBPUSDbuys == 0 && GBPUSDsells == 0 && GBPUSD_Deviation > 0)
      {
        Comment("Opening a GBPUSD sell trade...");
        Print("Short GBPUSD.");
        OrderSend(GBPUSDsym,OP_SELL,UseLots,MarketInfo(GBPUSDsym, MODE_BID),Slippage,0,0,"BOUGHT GBPUSD",MagicNumber,Red);
        Sleep(1000);
      }

      if (EURGBPbuys == 0 && EURGBPsells == 0 && EURGBP_Deviation > 0)
      {
        Comment("Opening a EURGBP sell trade...");
        Print("Short EURGBP.");
        OrderSend(EURGBPsym,OP_SELL,UseLots,MarketInfo(EURGBPsym, MODE_BID),Slippage,0,0,"BOUGHT EURGBP",MagicNumber,Red);
        Sleep(1000);
      }

      if (GBPJPYbuys == 0 && GBPJPYsells == 0 && GBPJPY_Deviation > 0)
      {
        Comment("Opening a GBPJPY sell trade...");
        Print("Short GBPJPY.");
        OrderSend(GBPJPYsym,OP_SELL,UseLots,MarketInfo(GBPJPYsym, MODE_BID),Slippage,0,0,"BOUGHT GBPJPY",MagicNumber,Red);
        Sleep(1000);
      }

      if (USDCHFbuys == 0 && USDCHFsells == 0 && USDCHF_Deviation > 0)
      {
        Comment("Opening a USDCHF sell trade...");
        Print("Short USDCHF.");
        OrderSend(USDCHFsym,OP_SELL,UseLots,MarketInfo(USDCHFsym, MODE_BID),Slippage,0,0,"BOUGHT USDCHF",MagicNumber,Red);
        Sleep(1000);
      }

      if (NZDUSDbuys == 0 && NZDUSDsells == 0 && NZDUSD_Deviation > 0)
      {
        Comment("Opening a NZDUSD sell trade...");
        Print("Short NZDUSD.");
        OrderSend(NZDUSDsym,OP_SELL,UseLots,MarketInfo(NZDUSDsym, MODE_BID),Slippage,0,0,"BOUGHT NZDUSD",MagicNumber,Red);
        Sleep(1000);
      }

      if (AUDJPYbuys == 0 && AUDJPYsells == 0 && AUDJPY_Deviation > 0)
      {
        Comment("Opening a AUDJPY sell trade...");
        Print("Short AUDJPY.");
        OrderSend(AUDJPYsym,OP_SELL,UseLots,MarketInfo(AUDJPYsym, MODE_BID),Slippage,0,0,"BOUGHT AUDJPY",MagicNumber,Red);
        Sleep(1000);
      }

      if (EURJPYbuys == 0 && EURJPYsells == 0 && EURJPY_Deviation > 0)
      {
        Comment("Opening a EURJPY sell trade...");
        Print("Short EURJPY.");
        OrderSend(EURJPYsym,OP_SELL,UseLots,MarketInfo(EURJPYsym, MODE_BID),Slippage,0,0,"BOUGHT EURJPY",MagicNumber,Red);
        Sleep(1000);
      }

      if (EURUSDsells == 0 && EURUSDbuys == 0 && EURUSD_Deviation < 0)
      {
        Comment("Opening a EURUSD buy trade...");
        Print("Long EURUSD.");
        OrderSend(EURUSDsym,OP_BUY,UseLots,MarketInfo(EURUSDsym, MODE_ASK),Slippage,0,0,"SOLD EURUSD",MagicNumber,Blue);
        Sleep(1000);
      }

      if (USDJPYsells == 0 && USDJPYbuys == 0 && USDJPY_Deviation < 0)
      {
        Comment("Opening a USDJPY buy trade...");
        Print("Long USDJPY.");
        OrderSend(USDJPYsym,OP_BUY,UseLots,MarketInfo(USDJPYsym, MODE_ASK),Slippage,0,0,"SOLD USDJPY",MagicNumber,Blue);
        Sleep(1000);
      }

      if (AUDUSDsells == 0 && AUDUSDbuys == 0 && AUDUSD_Deviation < 0)
      {
        Comment("Opening a AUDUSD buy trade...");
        Print("Long AUDUSD.");
        OrderSend(AUDUSDsym,OP_BUY,UseLots,MarketInfo(AUDUSDsym, MODE_ASK),Slippage,0,0,"SOLD AUDUSD",MagicNumber,Blue);
        Sleep(1000);
      }

      if (NZDJPYsells == 0 && NZDJPYbuys == 0 && NZDJPY_Deviation < 0)
      {
        Comment("Opening a NZDJPY buy trade...");
        Print("Long NZDJPY.");
        OrderSend(NZDJPYsym,OP_BUY,UseLots,MarketInfo(NZDJPYsym, MODE_ASK),Slippage,0,0,"SOLD NZDJPY",MagicNumber,Blue);
        Sleep(1000);
      }

      if (GBPCHFsells == 0 && GBPCHFbuys == 0 && GBPCHF_Deviation < 0)
      {
        Comment("Opening a GBPCHF buy trade...");
        Print("Long GBPCHF.");
        OrderSend(GBPCHFsym,OP_BUY,UseLots,MarketInfo(GBPCHFsym, MODE_ASK),Slippage,0,0,"SOLD GBPCHF",MagicNumber,Blue);
        Sleep(1000);
      }

      if (CHFJPYsells == 0 && CHFJPYbuys == 0 && CHFJPY_Deviation < 0)
      {
        Comment("Opening a CHFJPY buy trade...");
        Print("Long CHFJPY.");
        OrderSend(CHFJPYsym,OP_BUY,UseLots,MarketInfo(CHFJPYsym, MODE_ASK),Slippage,0,0,"SOLD CHFJPY",MagicNumber,Blue);
        Sleep(1000);
      }

      if (EURCHFsells == 0 && EURCHFbuys == 0 && EURCHF_Deviation < 0)
      {
        Comment("Opening a EURCHF buy trade...");
        Print("Long EURCHF.");
        OrderSend(EURCHFsym,OP_BUY,UseLots,MarketInfo(EURCHFsym, MODE_ASK),Slippage,0,0,"SOLD EURCHF",MagicNumber,Blue);
        Sleep(1000);
      }
    
  }

  return(0);
}

//+------------------------------------------------------------------+
//|   Keep track of lowest margin level and largest floating loss.   |
//+------------------------------------------------------------------+

void ExamineMarginAndFloat()
{
  if (AccountMargin() > 0.0)
  {
    PercentMarginLevel = StrToDouble(DoubleToStr(100 * AccountEquity() / AccountMargin(), 2));

    if (PercentMarginLevel < valLowestMarginLevel)
    {
      GlobalVariableSet(LowestMarginLevel, PercentMarginLevel);
      valLowestMarginLevel = PercentMarginLevel;
    }
  }

  if (EAPL < valLargestFloatingLoss)
  {
    GlobalVariableSet(LargestFloatingLoss, EAPL);
    valLargestFloatingLoss = StrToDouble(DoubleToStr(EAPL, 2));
  }

  if ((valLargestFloatingLoss / valLastFlatEq) * 100.0 < valMaxFloatingDrawdown)
  {
    valMaxFloatingDrawdown = StrToDouble(DoubleToStr((valLargestFloatingLoss / valLastFlatEq) * 100.0, 2));
    GlobalVariableSet(MaxFloatingDrawdown, valMaxFloatingDrawdown);
  }

  return(0);
}

//+------------------------------------------------------------------+
//|                      Print Info to Chart                         |
//+------------------------------------------------------------------+

void PrintChartComments()
{
  CommentString = 
        "STRATEGY: Trim every biggest loser that rises/falls above/below the 24-hour high/low for that currency pair if" +
        "\n" + ExceedenceTrigger + " pairs have risen/fallen above/below their 24-hour highs/lows, and place a trade in the opposite direction." +
        "\nREMINDER: Be FLAT (all trades closed) before depositing/withdrawing funds." +
        "\nAccount Type: " + AccountTypeString + " Account,   Leverage: " + DoubleToStr(Leverage,0) + ":1" +
        ",   Margin %: " + DoubleToStr(PercentMarginLevel,2) + "%,   Lowest Margin %: " + DoubleToStr(valLowestMarginLevel,2) + "%" +
        "\nExceedence Trigger: " + ExceedenceTrigger +
        "\nLargest Floating Loss: $" + DoubleToStr(valLargestFloatingLoss,2) + ",  Max Floating Drawdown %: " + DoubleToStr(valMaxFloatingDrawdown,2) + "%" +
        "\nBalance: $" + DoubleToStr(AccountBalance(),2) + ",   Equity: $" + DoubleToStr(AccountEquity(),2) +
        "\nLast Flat Balance: $" + DoubleToStr(valLastFlatBal,2) + ",   Last Flat Equity: $" + DoubleToStr(valLastFlatEq,2) +
        "\nDollar Profit Target: $" + DoubleToStr(DollarProfitTarget,2) + ",   Equity Profit Target: $" + DoubleToStr(valLastFlatEq+DollarProfitTarget,2) +
        "\nOpen Buys: " + DoubleToStr(NumBuys,0) + ",   Open Sells: " + DoubleToStr(NumSells,0) + ",   Total Open Trades: " + DoubleToStr(TotalTrades,0) +
        "\nEA PL: $" + DoubleToStr(EAPL,2) + ",   Buy PL: $" + DoubleToStr(BuyPL,2) + ",   Sell PL: $" + DoubleToStr(SellPL,2) +
        "\nBiggest Winner Symbol: " + BiggestWinnerSymbol + ",   Biggest Winner Type: " + BiggestWinnerType + ",  Biggest Winner Ticket: " + DoubleToStr(BiggestWinnerTicket,0) + ",   Biggest Winner PL: $" + DoubleToStr(BiggestWinnerPL,2) +
        "\nBiggest Loser Symbol: " + BiggestLoserSymbol + ",   Biggest Loser Type: " + BiggestLoserType + ",  Biggest Loser Ticket: " + DoubleToStr(BiggestLoserTicket,0) + ",   Biggest Loser PL: $" + DoubleToStr(BiggestLoserPL,2);
        
  Comment(CommentString);

  return(0);
}

//+------------------------------------------------------------------+
//|        Linear regression & deviation percentage function.        |
//+------------------------------------------------------------------+

double Deviation(string symbol, int RegressionLength,int Offset){
   
   // Linear Regression
   
   double SumY = 0;
   double Sum1 = 0;
   double Slope = 0;
   double DeviationPercent = 0;
   double Intercept = 0;
   double c;
   for (int x=0; x <= RegressionLength - 1; x++) {
      c = iClose(symbol, PERIOD_M15, x + Offset);
      SumY += c;
      Sum1 += x*c; }
   double SumBars = RegressionLength * (RegressionLength - 1)*0.5;
   double SumSqrBars = (RegressionLength - 1) * RegressionLength * (2 * RegressionLength - 1)/6;
	double Sum2 = SumBars * SumY;
	double Num1 = RegressionLength * Sum1 - Sum2;
	double Num2 = SumBars * SumBars - RegressionLength * SumSqrBars;
	if (Num2 != 0) Slope = Num1 / Num2;
	else Slope = 0;
	if (RegressionLength != 0) Intercept = (SumY - Slope * SumBars) / RegressionLength;
	else Intercept = 0;
	double LinearRegression = Intercept + Slope * (RegressionLength - 1);
	
	// Standard deviation from linear regression as a percentage of linear regression
	
	double StandardDeviation = iStdDev(symbol,PERIOD_M15,RegressionLength,0,MODE_EMA,PRICE_CLOSE,0);
   if (LinearRegression + StandardDeviation != 0) DeviationPercent = (1 - (LinearRegression / (LinearRegression + StandardDeviation)))*100;
   else DeviationPercent = 0;
   if (MarketInfo(symbol,MODE_BID) < LinearRegression) DeviationPercent = -DeviationPercent;   
	
	return(DeviationPercent);
}