//=============================================================================
//                                                            DeviantPush.mq4
//                                              Copyright © 2006, Derk Wehler
//                                                       derkwehler@gmail.com
//
//=============================================================================
#property copyright "Copyright © 2006, Derk Wehler"
#property link      "www.ArrogantFxBastards.com"

#include <LibOrderReliable_V1_1_2.mqh>
#include <LibDerksUtils.mqh>


// Input parameters
extern string	S1 = "== MONEY MANAGEMENT SETTINGS ==";
extern bool 	MoneyManagement 	= true;
extern bool 	BinaryMM	 		= true;
extern double	TradeSizePercent 	= 3;	// Change to whatever percent of equity you wish to risk.
extern double	Lots 				= 0.1;
extern double	MaxLots 			= 100.0;
extern string	S1z = " ";
extern string	S3 = "==== EA SETTINGS ====";
extern string	S3a = "------ SL, TP AND TRAIL ------";
extern int		TakeProfit			= 15;
extern int		StopLoss			= 15;
extern string	S3z = " ";
extern string	S4c = "------ GENERAL EA ------";
extern int		MagicSeed			= 17765;
extern string	ExpertName			= "JMA_Binary";
extern int		DebugLevel 			= 1;


static int 	prevBars = -1;

int 	MagicNumber;
double	SL;
double	TP;

double InnerUpper;
double InnerLower;
double MidUpper;
double MidLower;
double OuterUpper;
double OuterLower;



//=============================================================================
//	expert initialization function
//=============================================================================
int init()
{
	// Set up magic numbers:
    MagicNumber = MagicSeed + SymbolConst2Val(Symbol())*100 + TimeFrameConst2Val(Period());
	
	return (0);

	// ------------------------------------------------
	// Put code here to test indicators.  Sample:
	// ------------------------------------------------
	
    for (int i=0; i < 20; i++)
    {
        double OuterUpper 	= ObjectGetValueByShift("Reg_Outside2_upper1", i);
        double MidUpper 	= ObjectGetValueByShift("Reg_Outside_upper1", i);
        double InnerUpper 	= ObjectGetValueByShift("Reg_Inside_upper1", i);
        double InnerLower 	= ObjectGetValueByShift("Reg_Inside_lower1", i);
        double MidLower 	= ObjectGetValueByShift("Reg_Outside_lower1", i);
        double OuterLower 	= ObjectGetValueByShift("Reg_Outside2_lower1", i);
        Comment("\ni = ", i, "\nLine 1: ", OuterUpper, "\nLine 2: ", MidUpper, "\nLine 3: ", InnerUpper, "\nLine 4: ", InnerLower, "\nLine 5: ", MidLower, "\nLine 6: ", OuterLower);
        Sleep(2000);
    }
}
  
//=============================================================================
//	expert deinitialization function
//=============================================================================
int deinit()
{
	return (0);
}


//=============================================================================
//	Expert start function
//=============================================================================
int start()
{
	color	clr = CLR_NONE;
	double	price, priceA, priceB;
	int		op, ticket;
	int 	cnt, openPos, pendPos;
	int		pipsProfit;
	int 	type;
	double 	lotMM = Lots;
	
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	// Get the values of the LSMA Channel lines (used in various places)
	// For our purposes, taking the value of these 
	// lines 2 candles back should work best.
	InnerUpper 	= ObjectGetValueByShift("Reg_Inside_upper1", 0);
	InnerLower 	= ObjectGetValueByShift("Reg_Inside_lower1", 0);
	MidUpper 	= ObjectGetValueByShift("Reg_Outside_upper1", 0);
	MidLower 	= ObjectGetValueByShift("Reg_Outside_lower1", 0);
	OuterUpper 	= ObjectGetValueByShift("Reg_Outside2_upper1", 0);
	OuterLower 	= ObjectGetValueByShift("Reg_Outside2_lower1", 0);
	if (DebugLevel > 0)
		Comment("\nLine 1: ", OuterUpper, "\nLine 2: ", MidUpper, 
				"\nLine 3: ", InnerUpper, "\nLine 4: ", InnerLower, 
				"\nLine 5: ", MidLower, "\nLine 6: ", OuterLower);
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

	// Get total of all open positions
	openPos = NumOpenPositions(MagicNumber, OP_BOTH);
	pendPos = NumPendingOrders(MagicNumber, ALL_PENDING);
//	Print("Num of: Open: ", openPos, "   Pending: ", pendPos);
	
	if (openPos > 0)
		return(0);
		
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	// From here on, only perform this code at the start of a new candle
//	if (prevBars == Bars)
//		return(0);
//	prevBars = Bars;
	
	// Get the minium SL (& TP(?)) level
	// Apparently for longs (reverse for shorts of course), 
	// TP has to be minDist above Ask &
	// SL has to be minDist below Bid
	int minDist = MarketInfo(Symbol(), MODE_STOPLEVEL);
	minDist++;	// Add one to be sure
	
	bool changeOrder = false;
	
	// Only one trade at a time - If trade open, check for adjusting Pending
	if (pendPos > 0)
	{
		for (cnt=OrdersTotal()-1; cnt >= 0; cnt--)
		{
			OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
			if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) 
				continue;
		
			Print("Found pending... ticket = ", OrderTicket());
			if (OrderType() == OP_BUYSTOP)
			{
				if (OrderOpenPrice() - (minDist*Point) > Ask)
				{
					Print("OrderOpenPrice() - (minDist*Point) > Ask");
					changeOrder = true;
					price = Ask + (minDist*Point);
					SL = price - (StopLoss*Point);
					TP = price + (TakeProfit*Point);
					Print("NEW: Price: ", price, "    SL: ", SL, "   TP: ", TP);
				}
			}
			else if (OrderType() == OP_SELLSTOP)
			{
				if (OrderOpenPrice() + (minDist*Point) < Bid)
				{
					Print("OrderOpenPrice() + (minDist*Point) < Bid");
					changeOrder = true;
					price = Bid - (minDist*Point);
					SL = price + (StopLoss*Point);
					TP = price - (TakeProfit*Point);
					Print("NEW: Price: ", price, "    SL: ", SL, "   TP: ", TP);
				}
			}
		
			if (changeOrder)
			{
				Print("CALLING OrderModify... ");
				// Check whether the price has moved in our favour and we should
				OrderModifyReliable(OrderTicket(), price, SL, TP, 0, CLR_NONE);
			}
		}
	}
	
	// Check to see if we should place new pending
	else
	{	
		price = 0;
		if (Ask < MidLower - (minDist*Point))
		{
			Print("Ask: ", Ask, " <  midlower: ", MidLower);
			op = OP_BUYSTOP;
			price = MidLower;
			clr = Green;
			SL = price - (StopLoss*Point);
			TP = price + (TakeProfit*Point);
		}
		else if (Bid > MidUpper + (minDist*Point))
		{
			Print("Bid: ", Bid, " >  midupper: ", MidUpper);
			op = OP_SELLSTOP;
			price = MidUpper;
			clr = Green;
			SL = price + (StopLoss*Point);
			TP = price - (TakeProfit*Point);
		}

		// Open the new order
		if (price != 0)
		{
			Print("Lots begins at: ", lotMM);
			if (MoneyManagement)
			{
				lotMM = CalcLotsGivenRisk(TradeSizePercent, Lots, MaxLots, StopLoss);
				Print("Using MoneyManagement, lots becomes: ", lotMM);
			}
			
			if (BinaryMM)
			{
				lotMM = GetDualWinLots(lotMM, MagicNumber, TakeProfit, StopLoss);
				Print("Using Binary, lots becomes: ", lotMM);
			}
		
			ticket = OrderSendReliable(Symbol(), op, lotMM, price, 0, 
									SL, TP, ExpertName, MagicNumber, 0, clr);
		}
	}
								
	return(0);
}

