//+------------------------------------------------------------------+
//|                       Kaufman - price filtered 2.1 histo_EA.mq4  |
//|                        Generated with MetaEditor 5               |
//|                             with a little help from BestTraderEv |
//|                        https://www.forexfactory.com/besttraderev |                      |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
#property version   "1.00"
#property strict

#include <stderror.mqh>
#include <stdlib.mqh>

// Define the indicator name and parameters
#define ind_name "Kaufman - price filtered 2.1 histo"

enum enTriggerBar 
 { 
 Zero,      // Current Bar
 First,      // First Closed Bar
 };

// Input parameters
input double Lot=0.1; // Lot size
input int Slip=10; // Slippage
input double TP=0; // Take profit in points
input double SL=0; // Stop loss in points
input int Magic=12345; // Magic number for orders
input enTriggerBar TriggerBar=First;  // Position Trigger Bar

// Indicator parameters
input int AMA_Period = 10;
input ENUM_APPLIED_PRICE AMA_Price = PRICE_CLOSE;
input int Nfast = 2;
input int Nslow = 30;
input double GCoeff = 2;
input double PriceFilter = 15;
input double PriceFilterPhase = 0;

// Global variables
double previous_kAMA_Up,previous_kAMA_Down;
double current_kAMA_Up,current_kAMA_Down;
datetime prevTime;

int OnInit()
{
    prevTime = 0;
        
    return(INIT_SUCCEEDED);
}

void OnTick()
{
    // Check if a new candle has opened
    if (Time[0] <= prevTime) return;
    prevTime = Time[0];
    
    // Get the current values of the indicator
     current_kAMA_Up = iCustom(Symbol(), 0, ind_name, AMA_Period, AMA_Price, Nfast, Nslow, GCoeff, PriceFilter, PriceFilterPhase, 0, TriggerBar);
     current_kAMA_Down = iCustom(Symbol(), 0, ind_name, AMA_Period, AMA_Price, Nfast, Nslow, GCoeff, PriceFilter, PriceFilterPhase, 1, TriggerBar);
     previous_kAMA_Up = iCustom(Symbol(), 0, ind_name, AMA_Period, AMA_Price, Nfast, Nslow, GCoeff, PriceFilter, PriceFilterPhase, 0, TriggerBar+1);
     previous_kAMA_Down = iCustom(Symbol(), 0, ind_name, AMA_Period, AMA_Price, Nfast, Nslow, GCoeff, PriceFilter, PriceFilterPhase, 1, TriggerBar+1);
    
    // Conditions to open Buy trade
    if (current_kAMA_Up == 1 && previous_kAMA_Down == 1)
    {
        // Close Sell trades
        CloseTrades(OP_SELL);
        // Open Buy trade
        OpenTrade(OP_BUY);
    }
    
    // Conditions to open Sell trade
    if (current_kAMA_Down ==1 && previous_kAMA_Up == 1)
    {
        // Close Buy trades
        CloseTrades(OP_BUY);
        // Open Sell trade
        OpenTrade(OP_SELL);
    }
    
}

void OpenTrade(int tradeType)
{
    double price = (tradeType == OP_BUY) ? Ask : Bid;
    double tp = (TP > 0) ? (tradeType == OP_BUY ? NormalizeDouble(price + TP * Point,_Digits) : NormalizeDouble(price - TP * Point,_Digits)) : 0;
    double sl = (SL > 0) ? (tradeType == OP_BUY ? NormalizeDouble(price - SL * Point,_Digits) : NormalizeDouble(price + SL * Point,_Digits)) : 0;
    int ticket = OrderSend(Symbol(), tradeType, Lot, price, Slip, sl, tp, "AMA_EA", Magic, 0, clrGreen);
    if (ticket < 0)
    {
        Print("Error opening order: ", ErrorDescription(GetLastError()));
    }
    else
    {
        Print("Order opened successfully: ", OTS(tradeType), " ticket: ", ticket);
    }
}

void CloseTrades(int tradeType)
{
    bool tradeClosed = false;
    for (int i = OrdersTotal() - 1; i >= 0; i--)
    {
        if (OrderSelect(i, SELECT_BY_POS) && OrderType() == tradeType && OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
        {
            Print("Attempting to close order: ", OrderTicket(), " of type: ", OTS(tradeType));
            if (!OrderClose(OrderTicket(), OrderLots(), (tradeType == OP_BUY) ? Bid : Ask, Slip))
            {
                Print("Error closing order: ", ErrorDescription(GetLastError()));
            }
            else
            {
                Print("Order closed successfully: ", OTS(tradeType), " ticket: ", OrderTicket());
                tradeClosed = true;
            }
        }
    }
    if (!tradeClosed)
    {
        Print("No ", OTS(tradeType), " trades to close.");
    }
}

string OTS(int n)
{
    int p[6]={OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT, OP_BUYSTOP, OP_SELLSTOP};
    string sp[6]={"BUY", "SELL", "BUYLIMIT", "SELLLIMIT", "BUYSTOP", "SELLSTOP"};
    for (int i=0; i<6; i++) if (p[i]==n) return sp[i];
    return "--";
}
