//+------------------------------------------------------------------+
//|                                                Price Action Test |
//|                                                    Andriy Moraru |
//|                                         http://www.earnforex.com |
//|            							                            2011 |
//+------------------------------------------------------------------+
#property copyright "www.EarnForex.com, 2010"
#property link      "http://www.earnforex.com"
#property version   "1.0"

#property description "Trades using trailing stop with reverse. Initial direction is random."

#include <Trade/Trade.mqh>
#include <Trade/PositionInfo.mqh>

#define LONG 1
#define SHORT 2

input int StopLoss = 100; // Isn't used
input int TakeProfit = 0;
input int Slippage = 100; 	// Tolerated slippage in pips, pips are fractional
input double iLots = 0.1;
input int ATRper = 24;

// Main trading objects
CTrade *Trade;
CPositionInfo PositionInfo;

// Global variables
bool HaveLongPosition;
bool HaveShortPosition;
ulong LastBars = 0;
double SL, TP;
int LastPosition = 0;
int random;
double Lots;
int myATR;

//+------------------------------------------------------------------+
//| Expert Initialization Function                                   |
//+------------------------------------------------------------------+
void OnInit()
{
	// Initialize the Trade class object
	Trade = new CTrade;
	Trade.SetDeviationInPoints(Slippage);
	srand(TimeCurrent());
  	random = rand();
   myATR = iATR(NULL, 0, ATRper);
}

//+------------------------------------------------------------------+
//| Expert Deinitialization Function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
	delete Trade;
}

//+------------------------------------------------------------------+
//| Expert Every Tick Function                                       |
//+------------------------------------------------------------------+
void OnTick()
{
	if (TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) == false) return;
	
   // Getting the ATR values
   double ATR[1];
   ArraySetAsSeries(ATR, true);
   if (CopyBuffer(myATR, 0, 0, 1, ATR) != 1) return;
   // You can uncomment this line if you want to use ATR-based position sizing
   //Lots = NormalizeDouble(0.01 * AccountInfoDouble(ACCOUNT_BALANCE) / (ATR[0] * 100000), 1);
   // Reverse-Martingale position sizing
   Lots = NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE) / 10000 * 1.5, 1);
   ATR[0] *= 3;

   if (ATR[0] <= (SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL) + SymbolInfoInteger(Symbol(), SYMBOL_SPREAD)) * _Point) ATR[0] = (SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL) + SymbolInfoInteger(Symbol(), SYMBOL_SPREAD)) * _Point;

  	// Check what position is currently open
 	GetPositionStates();
   
 	// Adjust SL and TP of the current position
 	if ((HaveLongPosition) || (HaveShortPosition)) AdjustSLTP(ATR[0]);
   else
	{
      double Ask, Bid;
   
   	// Buy condition
   	if (((LastPosition == 0) && (random % 2 == 0)) || (LastPosition == SHORT))
   	{
  			for (int i = 0; i < 10; i++)
  			{
  		   	Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
  				Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
  				// Bid and Ask are swapped to preserve the probabilities and decrease/increase profit/loss size
  		   	SL = NormalizeDouble(Bid - ATR[0], _Digits);
  		   	if (TakeProfit) TP = NormalizeDouble(Bid + TakeProfit * _Point, _Digits);
  		   	else TP = 0;
  				Trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, Lots, Ask, SL, TP);
  				Sleep(1000);
  				if ((Trade.ResultRetcode() != 10008) && (Trade.ResultRetcode() != 10009) && (Trade.ResultRetcode() != 10010))
  					Print("Long Position Open Return Code: ", Trade.ResultRetcodeDescription());
  				else return;
  			}
   	}
   	// Sell condition
   	else if (((LastPosition == 0) && (random % 2 != 0)) || (LastPosition == LONG))
   	{
  			for (int i = 0; i < 10; i++)
  			{
  		   	Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
  				Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
  				// Bid and Ask are swapped to preserve the probabilities and decrease/increase profit/loss size
  		      SL = NormalizeDouble(Ask + ATR[0], _Digits);
  				if (TakeProfit) TP = NormalizeDouble(Ask - TakeProfit * _Point, _Digits);
  				else TP = 0;
  				Trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, Lots, Bid, SL, TP);
  				Sleep(1000);
  				if ((Trade.ResultRetcode() != 10008) && (Trade.ResultRetcode() != 10009) && (Trade.ResultRetcode() != 10010))
  					Print("Short Position Open Return Code: ", Trade.ResultRetcodeDescription());
  				else return;
  			}
   	}
	}
}

//+------------------------------------------------------------------+
//| Check What Position is Currently Open										|
//+------------------------------------------------------------------+
void GetPositionStates()
{
	// Is there a position on this currency pair?
	if (PositionInfo.Select(_Symbol))
	{
		if (PositionInfo.PositionType() == POSITION_TYPE_BUY)
		{
			HaveLongPosition = true;
			HaveShortPosition = false;
		}
		else if (PositionInfo.PositionType() == POSITION_TYPE_SELL)
		{ 
			HaveLongPosition = false;
			HaveShortPosition = true;
		}
   	if (HaveLongPosition) LastPosition = LONG;
   	else if (HaveShortPosition) LastPosition = SHORT;
	}
	else 
	{
		HaveLongPosition = false;
		HaveShortPosition = false;
	}
}

//+------------------------------------------------------------------+
//| Close Open Position																|
//+------------------------------------------------------------------+
void ClosePrevious()
{
	for (int i = 0; i < 10; i++)
	{
		Trade.PositionClose(_Symbol, Slippage);
		if ((Trade.ResultRetcode() != 10008) && (Trade.ResultRetcode() != 10009) && (Trade.ResultRetcode() != 10010))
			Print("Position Close Return Code: ", Trade.ResultRetcodeDescription());
		else return;
	}
}

//+------------------------------------------------------------------+
//| Adjust Stop-Loss and TakeProfit of the Open Position					|
//+------------------------------------------------------------------+
void AdjustSLTP(double SLparam)
{
	// Is there a position on this currency pair?
	if (PositionInfo.Select(_Symbol))
	{
		if (PositionInfo.PositionType() == POSITION_TYPE_BUY)
		{
		   double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
			SL = NormalizeDouble(Bid - SLparam/* * _Point*/, _Digits);
			TP = NormalizeDouble(PositionInfo.TakeProfit(), _Digits);
			if (SL > NormalizeDouble(PositionInfo.StopLoss(), _Digits))
			{
				for (int i = 0; i < 10; i++)
				{
					Trade.PositionModify(_Symbol, SL, TP);
					if ((Trade.ResultRetcode() != 10008) && (Trade.ResultRetcode() != 10009) && (Trade.ResultRetcode() != 10010))
						Print("Long Position Modify Return Code: ", Trade.ResultRetcodeDescription());
					else return;
				}
			}
		}
		else if (PositionInfo.PositionType() == POSITION_TYPE_SELL)
		{ 
			double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
			SL = NormalizeDouble(Ask + SLparam/* * _Point*/, _Digits);
			TP = NormalizeDouble(PositionInfo.TakeProfit(), _Digits);
			if (SL < NormalizeDouble(PositionInfo.StopLoss(), _Digits))
			{
				for (int i = 0; i < 10; i++)
				{
					Trade.PositionModify(_Symbol, SL, TP);
					if ((Trade.ResultRetcode() != 10008) && (Trade.ResultRetcode() != 10009) && (Trade.ResultRetcode() != 10010))
						Print("Short Position Modify Return Code: ", Trade.ResultRetcodeDescription());
					else return;
				}
			}
		}
	}
}
//+------------------------------------------------------------------+

