//-------------------------------------------------------------
// Copyright 2018, Econome for Forex-Station.com //
// 3 Averages Cross EA with KEfficiency Filter
// Using AllAverages3.1 by TrendLab
// And KEfficiency by 

#property copyright "Copyright 2018, Econome for Forex-Station.com"
#property link      "http://www.Forex-Station.com"

#include <stdlib.mqh>
#include <WinUser32.mqh>

// exported variables
extern int HoursFrom6 = 1;
extern int HoursTo6 = 23;
extern double AAFPrice = 0;
extern double AAFperiod = 3;
extern double AAFMethod = 1;
extern double AALPrice = 0;
extern double AALPeriod = 8;
extern double AALMethod = 0;
extern double AAMPrice = 0;
extern double AAMperiod = 5;
extern double AAMMethod = 0;
extern double KEPer = 8;
extern double KEthreshold = -1;
extern int OpenOrdersLimit11 = 3;
extern int StopLoss20 = 23;
extern int TakeProfit20 = 75;
extern double BalanceRiskPercent20 = 1;


// local variables
double PipValue=1;    // this variable is here to support 5-digit brokers
bool Terminated = false;
string LF = "\n";  // use this in custom or utility blocks where you need line feeds
int NDigits = 4;   // used mostly for NormalizeDouble in Flex type blocks
int ObjCount = 0;  // count of all objects created on the chart, allows creation of objects with unique names
int current = 0;   // current bar index, used by Cross Up, Cross Down and many other blocks
int varylots[101]; // used by Buy Order Varying, Sell Order Varying and similar

datetime BarTime1 = 0;


int init()
{
    NDigits = Digits;
    
    if (false) ObjectsDeleteAll();      // clear the chart
    
    
    Comment("");    // clear the chart
    return (0);
}

// Expert start
int start()
{
    if (Bars < 10)
    {
        Comment("Not enough bars");
        return (0);
    }
    if (Terminated == true)
    {
        Comment("EA Terminated.");
        return (0);
    }
    
    OnEveryNewBar1();
    return (0);
}

void OnEveryNewBar1()
{
    PipValue = 1;
    if (NDigits == 3 || NDigits == 5) PipValue = 10;
    if (BarTime1 < Time[0])
    {
        // we have a new bar opened
        BarTime1 = Time[0]; // keep the new bar open time
        HoursFilter6();
        
    }
}

void HoursFilter6()
{
    int datetime800 = TimeLocal();
    int hour0 = TimeHour(datetime800);
    
    if ((HoursFrom6 < HoursTo6 && hour0 >= HoursFrom6 && hour0 < HoursTo6) ||
    (HoursFrom6 > HoursTo6 && (hour0 < HoursTo6 || hour0 >= HoursFrom6)))
    {
        TechnicalAnalysis2xOr18();
        TechnicalAnalysis2xOr19();
        
    }
}

void TechnicalAnalysis2xOr18()
{
    if ((iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AAFPrice,AAFperiod,0,AAFMethod,1,0,0,"alert.wav","alert2.wav",0,2) >= iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AALPrice,AALPeriod,0,AALMethod,1,0,0,"alert.wav","alert2.wav",0,2)) || (iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AAMPrice,AAMperiod,0,AAMMethod,1,0,0,"alert.wav","alert2.wav",0,2) >= iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AALPrice,AALPeriod,0,AALMethod,1,0,0,"alert.wav","alert2.wav",0,2)))
    {
        TechnicalAnalysis2x10();
        
    }
}

void TechnicalAnalysis2x10()
{
    if ((iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AAFPrice,AAFperiod,0,AAFMethod,1,0,0,"alert.wav","alert2.wav",0,1) < iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AALPrice,AALPeriod,0,AALMethod,1,0,0,"alert.wav","alert2.wav",0,1)) && (iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AAMPrice,AAMperiod,0,AAMMethod,1,0,0,"alert.wav","alert2.wav",0,1) < iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AALPrice,AALPeriod,0,AALMethod,1,0,0,"alert.wav","alert2.wav",0,1)))
    {
        TechnicalAnalysis3x17();
        
    }
}

void TechnicalAnalysis3x17()
{
    if ((0 == 0) && (iCustom(NULL, PERIOD_CURRENT, "!        ! KEfficiencyRatio",KEPer,0,1) < (-1*KEthreshold)) && (Close[1] < High[3]))
    {
        CheckOrderCount11();
        
    }
}

void CheckOrderCount11()
{
    int count = 0;
    for (int i=OrdersTotal()-1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
        if (OrderSymbol() == Symbol())
        if (OrderMagicNumber() == 1)
        {
            count++;
        }
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
    if (count < OpenOrdersLimit11)
    {
        BuyOrderRiskFixed20();
        
    }
}

void BuyOrderRiskFixed20()
{
    double lotsize = MarketInfo(Symbol(),MODE_LOTSIZE) / AccountLeverage();
    double pipsize = 1 * 10;
    double maxlots = AccountFreeMargin() / 100 * BalanceRiskPercent20 / lotsize * pipsize;
    if (StopLoss20 == 0) Print("OrderSend() error - stoploss can not be zero");
    double lots = maxlots / StopLoss20 * 10;
    
    // calculate lot size based on current risk
    double lotvalue = 0.001;
    double minilot = MarketInfo(Symbol(), MODE_MINLOT);
    int powerscount = 0;
    while (minilot < 1)
    {
        minilot = minilot * MathPow(10, powerscount);
        powerscount++;
    }
    lotvalue = NormalizeDouble(lots, powerscount - 1);
    
    if (lotvalue < MarketInfo(Symbol(), MODE_MINLOT))    // make sure lot is not smaller than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MINLOT);
    }
    if (lotvalue > MarketInfo(Symbol(), MODE_MAXLOT))    // make sure lot is not greater than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MAXLOT);
    }
    double SL = Ask - StopLoss20*PipValue*Point;
    if (StopLoss20 == 0) SL = 0;
    double TP = Ask + TakeProfit20*PipValue*Point;
    if (TakeProfit20 == 0) TP = 0;
    
    int ticket = -1;
    if (true)
    ticket = OrderSend(Symbol(), OP_BUY, lotvalue, Ask, 2, 0, 0, "My Expert", 1, 0, Blue);
    else
    ticket = OrderSend(Symbol(), OP_BUY, lotvalue, Ask, 2, SL, TP, "My Expert", 1, 0, Blue);
    if (ticket > -1)
    {
        if (true)
        {
            bool sel = OrderSelect(ticket, SELECT_BY_TICKET);
            bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Blue);
            if (ret == false)
            Print("OrderModify() error - ", ErrorDescription(GetLastError()));
        }
            
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
}

//!     ! AllAverages_v3.1",0,SMApri,SMAper,0,SMAmet,1,0,0,"alert.wav","alert2.wav",0,shift)

void TechnicalAnalysis2xOr19()
{
    if ((iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AAFPrice,AAFperiod,0,AAFMethod,1,0,0,"alert.wav","alert2.wav",0,2) <= iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AALPrice,AALPeriod,0,AALMethod,1,0,0,"alert.wav","alert2.wav",0,2)) || (iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AAMPrice,AAMperiod,0,AAMMethod,1,0,0,"alert.wav","alert2.wav",0,2) <= iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AALPrice,AALPeriod,0,AALMethod,1,0,0,"alert.wav","alert2.wav",0,2)))
    {
        TechnicalAnalysis2x15();
        
    }
}

void TechnicalAnalysis2x15()
{
    if ((iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AAFPrice,AAFperiod,0,AAFMethod,1,0,0,"alert.wav","alert2.wav",0,1) > iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AALPrice,AALPeriod,0,AALMethod,1,0,0,"alert.wav","alert2.wav",0,1)) && (iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AAMPrice,AAMperiod,0,AAMMethod,1,0,0,"alert.wav","alert2.wav",0,1) > iCustom(NULL, PERIOD_CURRENT, "!     ! AllAverages_v3.1",0,AALPrice,AALPeriod,0,AALMethod,1,0,0,"alert.wav","alert2.wav",0,1)))
    {
        TechnicalAnalysis3x16();
        
    }
}

void TechnicalAnalysis3x16()
{
    if ((0 == 0) && (iCustom(NULL, PERIOD_CURRENT, "!        ! KEfficiencyRatio",KEPer,0,1) > (KEthreshold)) && (Close[1] > Low[3]))
    {
        CheckOrderCount12();
        
    }
}

void CheckOrderCount12()
{
    int count = 0;
    for (int i=OrdersTotal()-1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
        if (OrderSymbol() == Symbol())
        if (OrderMagicNumber() == 2)
        {
            count++;
        }
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
    if (count < OpenOrdersLimit11)
    {
        SellOrderRiskFixed21();
        
    }
}

void SellOrderRiskFixed21()
{
    double lotsize = MarketInfo(Symbol(),MODE_LOTSIZE) / AccountLeverage();
    double pipsize = 1 * 10;
    double maxlots = AccountFreeMargin() / 100 * BalanceRiskPercent20 / lotsize * pipsize;
    if (StopLoss20 == 0) Print("OrderSend() error - stoploss can not be zero");
    double lots = maxlots / StopLoss20 * 10;
    
    // calculate lot size based on current risk
    double lotvalue = 0.001;
    double minilot = MarketInfo(Symbol(), MODE_MINLOT);
    int powerscount = 0;
    while (minilot < 1)
    {
        minilot = minilot * MathPow(10, powerscount);
        powerscount++;
    }
    lotvalue = NormalizeDouble(lots, powerscount - 1);
    
    if (lotvalue < MarketInfo(Symbol(), MODE_MINLOT))    // make sure lot is not smaller than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MINLOT);
    }
    if (lotvalue > MarketInfo(Symbol(), MODE_MAXLOT))    // make sure lot is not greater than allowed value
    {
        lotvalue = MarketInfo(Symbol(), MODE_MAXLOT);
    }
    double SL = Bid + StopLoss20*PipValue*Point;
    if (StopLoss20 == 0) SL = 0;
    double TP = Bid - TakeProfit20*PipValue*Point;
    if (TakeProfit20 == 0) TP = 0;
    
    int ticket = -1;
    if (true)
    ticket = OrderSend(Symbol(), OP_SELL, lotvalue, Bid, 4, 0, 0, "My Expert", 2, 0, Red);
    else
    ticket = OrderSend(Symbol(), OP_SELL, lotvalue, Bid, 4, SL, TP, "My Expert", 2, 0, Red);
    if (ticket > -1)
    {
        if (true)
        {
            bool sel = OrderSelect(ticket, SELECT_BY_TICKET);
            bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Red);
            if (ret == false)
            Print("OrderModify() error - ", ErrorDescription(GetLastError()));
        }
            
    }
    else
    {
        Print("OrderSend() error - ", ErrorDescription(GetLastError()));
    }
}



int deinit()
{
    if (false) ObjectsDeleteAll();
    
    
    return (0);
}

