last ...
This commit is contained in:
@@ -0,0 +1,547 @@
|
|||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| XKI_MTF_EA.mq5
|
||||||
|
//| SaherElm IT Center - Strategy using XKI
|
||||||
|
//| Author: Hadi Khazaee Asl
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
#property strict
|
||||||
|
|
||||||
|
//
|
||||||
|
// Imports ...
|
||||||
|
#include "../Libraries/x-saherelm.common.lib.mq5"
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
input string InpSymbol = "XAUUSDb";
|
||||||
|
input ENUM_TIMEFRAMES InpSignalTF = PERIOD_H1; // Signal timeframe (H1)
|
||||||
|
input int InpKiLength = 26; // KI length (XKI input)
|
||||||
|
input bool InpShowKI = true; // (XKI input)
|
||||||
|
input int InpCalcLastBars = 1500; // (XKI input)
|
||||||
|
|
||||||
|
input bool InpUseRSI = true; // Use RSI confirmation
|
||||||
|
input int InpRSIPeriod = 14;
|
||||||
|
input int InpRSIPrice = PRICE_CLOSE;
|
||||||
|
|
||||||
|
input bool InpUseH4Filter = true; // Confirm with H4
|
||||||
|
input bool InpUseD1Filter = false; // Confirm with D1
|
||||||
|
input bool InpRequireBothFilters = false; // If true, require BOTH H4 and D1 agreement; else either
|
||||||
|
|
||||||
|
input double InpFixedLot = 0.10; // Fixed lot size
|
||||||
|
input double InpRiskATRMult = 0.0; // Add ATR padding to stop (0=disabled)
|
||||||
|
input int InpATRPeriod = 14;
|
||||||
|
|
||||||
|
input double InpRR = 2.0; // Reward:Risk target
|
||||||
|
input bool InpTrailByKI = true; // Trail stop to KI
|
||||||
|
input int InpSlippagePoints = 20; // Max slippage in points
|
||||||
|
input int InpMaxSpreadPoints = 200; // Max allowed spread in points
|
||||||
|
|
||||||
|
input bool InpAvoidAsianSession = true; // Avoid 22:00–06:00 server time
|
||||||
|
input int InpAsianStartHour = 22;
|
||||||
|
input int InpAsianEndHour = 6;
|
||||||
|
|
||||||
|
input bool InpAvoidNewsWindow = false; // Placeholder flag
|
||||||
|
input int InpNewsWindowMinutes = 60; // Skip trades within +/- minutes
|
||||||
|
|
||||||
|
input int InpBarsLookbackSignal = 2; // Lookback bars for signal (e.g., last closed bar)
|
||||||
|
|
||||||
|
// Magic number and comments
|
||||||
|
input int InpMagic = 260126;
|
||||||
|
input string InpOrderComment = "XKI_MTF_EA";
|
||||||
|
|
||||||
|
// iCustom indicator path (relative to Indicators folder if compiled there)
|
||||||
|
string g_xkiIndicatorPath = "x-saherelm.x121.xki"; // the compiled name; adjust if different
|
||||||
|
|
||||||
|
// Buffers indices as per the indicator
|
||||||
|
#define KI_BUFFER_INDEX 0
|
||||||
|
#define KI_COLOR_IDX_BUFFER_INDEX 1
|
||||||
|
#define KI_STATE_BUFFER_INDEX 2
|
||||||
|
|
||||||
|
// States from indicator
|
||||||
|
#define BULLISH_STATE 1
|
||||||
|
#define NEUTURAL_STATE 0
|
||||||
|
#define BEARISH_STATE -1
|
||||||
|
|
||||||
|
// Globals
|
||||||
|
int g_digits;
|
||||||
|
double g_point;
|
||||||
|
MqlTick g_tick;
|
||||||
|
int g_atrHandleH1 = INVALID_HANDLE;
|
||||||
|
int g_atrHandleH4 = INVALID_HANDLE;
|
||||||
|
int g_atrHandleD1 = INVALID_HANDLE;
|
||||||
|
int g_rsiHandleH1 = INVALID_HANDLE;
|
||||||
|
int g_rsiHandleH4 = INVALID_HANDLE;
|
||||||
|
int g_rsiHandleD1 = INVALID_HANDLE;
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
// OnInit
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
int OnInit()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
g_digits = (int)SymbolInfoInteger(InpSymbol, SYMBOL_DIGITS);
|
||||||
|
g_point = SymbolInfoDouble(InpSymbol, SYMBOL_POINT);
|
||||||
|
|
||||||
|
if (!SymbolInfoTick(InpSymbol, g_tick))
|
||||||
|
{
|
||||||
|
Print("Failed to get tick for symbol: ", InpSymbol);
|
||||||
|
return INIT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quick validation
|
||||||
|
if (InpKiLength < 5)
|
||||||
|
{
|
||||||
|
Print("Invalid KI length: ", InpKiLength);
|
||||||
|
return INIT_PARAMETERS_INCORRECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
GetOrCreateATRHandle(InpSymbol, InpSignalTF, InpATRPeriod);
|
||||||
|
if (InpUseH4Filter)
|
||||||
|
GetOrCreateATRHandle(InpSymbol, PERIOD_H4, InpATRPeriod);
|
||||||
|
if (InpUseD1Filter)
|
||||||
|
GetOrCreateATRHandle(InpSymbol, PERIOD_D1, InpATRPeriod);
|
||||||
|
|
||||||
|
//
|
||||||
|
GetOrCreateRSIHandle(InpSymbol, InpSignalTF, InpRSIPeriod, InpRSIPrice);
|
||||||
|
if (InpUseH4Filter)
|
||||||
|
GetOrCreateRSIHandle(InpSymbol, PERIOD_H4, InpRSIPeriod, InpRSIPrice);
|
||||||
|
if (InpUseD1Filter)
|
||||||
|
GetOrCreateRSIHandle(InpSymbol, PERIOD_D1, InpRSIPeriod, InpRSIPrice);
|
||||||
|
|
||||||
|
//
|
||||||
|
return INIT_SUCCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
// OnDeinit
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void OnDeinit(const int reason)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
if (g_atrHandleH1 != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(g_atrHandleH1);
|
||||||
|
g_atrHandleH1 = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if (g_atrHandleH4 != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(g_atrHandleH4);
|
||||||
|
g_atrHandleH4 = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if (g_atrHandleD1 != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(g_atrHandleD1);
|
||||||
|
g_atrHandleD1 = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
if (g_rsiHandleH1 != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(g_rsiHandleH1);
|
||||||
|
g_rsiHandleH1 = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if (g_rsiHandleH4 != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(g_rsiHandleH4);
|
||||||
|
g_rsiHandleH4 = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if (g_rsiHandleD1 != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(g_rsiHandleD1);
|
||||||
|
g_rsiHandleD1 = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
// OnTick
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void OnTick()
|
||||||
|
{
|
||||||
|
if (_Symbol != InpSymbol)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Basic trading safety
|
||||||
|
if (!SymbolInfoTick(InpSymbol, g_tick))
|
||||||
|
return;
|
||||||
|
double spreadPoints = GetSpread(InpSymbol);
|
||||||
|
if (spreadPoints > InpMaxSpreadPoints)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (InpAvoidAsianSession)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
MqlDateTime now = GetCurrentTime();
|
||||||
|
int hr = now.hour;
|
||||||
|
if (IsHourInRange(hr, InpAsianStartHour, InpAsianEndHour))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InpAvoidNewsWindow)
|
||||||
|
{
|
||||||
|
// Placeholder: implement your own calendar integration
|
||||||
|
// Skip trading in a window near news. Here we simply return.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only process on new bar of signal timeframe
|
||||||
|
static datetime lastSignalBarTime = 0;
|
||||||
|
datetime currentSignalBarTime = GetLastClosedBarTime(InpSymbol, InpSignalTF);
|
||||||
|
if (currentSignalBarTime == 0 || currentSignalBarTime == lastSignalBarTime)
|
||||||
|
return;
|
||||||
|
lastSignalBarTime = currentSignalBarTime;
|
||||||
|
|
||||||
|
// Get signal state and KI on signal TF (last closed bar)
|
||||||
|
int signalBarShift = InpBarsLookbackSignal; // 1=last closed, 2=previous
|
||||||
|
int stateSignal;
|
||||||
|
double kiSignal, closeSignal;
|
||||||
|
if (!GetXKIStateAndKI(InpSymbol, InpSignalTF, signalBarShift, stateSignal, kiSignal))
|
||||||
|
return;
|
||||||
|
closeSignal = iClose(InpSymbol, InpSignalTF, signalBarShift);
|
||||||
|
|
||||||
|
// RSI confirmation
|
||||||
|
if (InpUseRSI)
|
||||||
|
{
|
||||||
|
double rsi = GetRSIValue(InpSymbol, InpSignalTF, InpRSIPeriod, InpRSIPrice, signalBarShift);
|
||||||
|
if (rsi == EMPTY_VALUE)
|
||||||
|
return;
|
||||||
|
if (stateSignal == BULLISH_STATE && rsi <= 50.0)
|
||||||
|
return;
|
||||||
|
if (stateSignal == BEARISH_STATE && rsi >= 50.0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Higher timeframe agreement
|
||||||
|
bool agreesH4 = true, agreesD1 = true;
|
||||||
|
if (InpUseH4Filter)
|
||||||
|
agreesH4 = HigherTFAgrees(InpSymbol, PERIOD_H4, signalBarShift, stateSignal);
|
||||||
|
if (InpUseD1Filter)
|
||||||
|
agreesD1 = HigherTFAgrees(InpSymbol, PERIOD_D1, signalBarShift, stateSignal);
|
||||||
|
|
||||||
|
bool filterOK = true;
|
||||||
|
if (InpUseH4Filter || InpUseD1Filter)
|
||||||
|
{
|
||||||
|
if (InpRequireBothFilters)
|
||||||
|
filterOK = (agreesH4 && agreesD1);
|
||||||
|
else
|
||||||
|
filterOK = ((InpUseH4Filter && agreesH4) || (InpUseD1Filter && agreesD1));
|
||||||
|
}
|
||||||
|
if (!filterOK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Neutral or invalid skip
|
||||||
|
if (stateSignal == NEUTURAL_STATE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ensure no open positions for this symbol/magic
|
||||||
|
if (HasOpenPosition(InpSymbol, InpMagic))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Prepare trade params
|
||||||
|
double atrPad = 0.0;
|
||||||
|
if (InpRiskATRMult > 0.0)
|
||||||
|
{
|
||||||
|
double atr = GetATRValue(InpSymbol, InpSignalTF, InpATRPeriod, signalBarShift);
|
||||||
|
if (atr != EMPTY_VALUE && atr > 0)
|
||||||
|
atrPad = atr * InpRiskATRMult;
|
||||||
|
}
|
||||||
|
|
||||||
|
double sl, tp;
|
||||||
|
bool isBuy = (stateSignal == BULLISH_STATE);
|
||||||
|
if (isBuy)
|
||||||
|
{
|
||||||
|
sl = kiSignal - atrPad;
|
||||||
|
tp = closeSignal + (closeSignal - sl) * InpRR;
|
||||||
|
PlaceOrder(InpSymbol, ORDER_TYPE_BUY, InpFixedLot, sl, tp);
|
||||||
|
}
|
||||||
|
else if (stateSignal == BEARISH_STATE)
|
||||||
|
{
|
||||||
|
sl = kiSignal + atrPad;
|
||||||
|
tp = closeSignal - (sl - closeSignal) * InpRR;
|
||||||
|
PlaceOrder(InpSymbol, ORDER_TYPE_SELL, InpFixedLot, sl, tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// After placement, trailing handled in OnTimer or OnTick below
|
||||||
|
if (InpTrailByKI)
|
||||||
|
TrailStopsByKI();
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
// Utilities
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//
|
||||||
|
// Create or reuse an ATR handle for the given TF ...
|
||||||
|
int GetOrCreateATRHandle(
|
||||||
|
string symbol,
|
||||||
|
ENUM_TIMEFRAMES tf,
|
||||||
|
int period //
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int h = g_atrHandleH1;
|
||||||
|
if (tf == PERIOD_H4)
|
||||||
|
h = g_atrHandleH4;
|
||||||
|
else if (tf == PERIOD_D1)
|
||||||
|
h = g_atrHandleD1;
|
||||||
|
if (h == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
h = iATR(symbol, tf, period);
|
||||||
|
if (h == INVALID_HANDLE)
|
||||||
|
Print("Failed to create ATR handle: ", symbol, " ", EnumToString(tf), " period=", period);
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read ATR value for a specific bar shift (1=last closed bar) ...
|
||||||
|
double GetATRValue(
|
||||||
|
string symbol,
|
||||||
|
ENUM_TIMEFRAMES tf,
|
||||||
|
int period,
|
||||||
|
int shift //
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int h = GetOrCreateATRHandle(symbol, tf, period);
|
||||||
|
if (h == INVALID_HANDLE)
|
||||||
|
return EMPTY_VALUE;
|
||||||
|
|
||||||
|
//
|
||||||
|
double buff[];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Copy exactly one value at 'shift' ...
|
||||||
|
int copied = CopyBuffer(h, 0, shift, 1, buff);
|
||||||
|
if (copied != 1 || !MathIsValidNumber(buff[0]))
|
||||||
|
return EMPTY_VALUE;
|
||||||
|
|
||||||
|
//
|
||||||
|
return buff[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create or reuse an RSI handle for the given TF ...
|
||||||
|
int GetOrCreateRSIHandle(
|
||||||
|
string symbol,
|
||||||
|
ENUM_TIMEFRAMES tf,
|
||||||
|
int period,
|
||||||
|
int appliedPrice //
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
int h = g_rsiHandleH1;
|
||||||
|
if (tf == PERIOD_H4)
|
||||||
|
h = g_rsiHandleH4;
|
||||||
|
else if (tf == PERIOD_D1)
|
||||||
|
h = g_rsiHandleD1;
|
||||||
|
if (h == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
h = iRSI(symbol, tf, period, appliedPrice);
|
||||||
|
if (h == INVALID_HANDLE)
|
||||||
|
Print("Failed to create RSI handle: ", symbol, " ", EnumToString(tf), " period=", period, " price=", appliedPrice);
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read RSI value for a specific bar shift (1=last closed bar) ..
|
||||||
|
double GetRSIValue(
|
||||||
|
string symbol,
|
||||||
|
ENUM_TIMEFRAMES tf,
|
||||||
|
int period,
|
||||||
|
int appliedPrice,
|
||||||
|
int shift //
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int h = GetOrCreateRSIHandle(symbol, tf, period, appliedPrice);
|
||||||
|
if (h == INVALID_HANDLE)
|
||||||
|
return EMPTY_VALUE;
|
||||||
|
double buff[];
|
||||||
|
int copied = CopyBuffer(h, 0, shift, 1, buff);
|
||||||
|
if (copied != 1 || !MathIsValidNumber(buff[0]))
|
||||||
|
return EMPTY_VALUE;
|
||||||
|
return buff[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
datetime GetLastClosedBarTime(string symbol, ENUM_TIMEFRAMES tf)
|
||||||
|
{
|
||||||
|
datetime times[];
|
||||||
|
if (CopyTime(symbol, tf, 0, 3, times) <= 1)
|
||||||
|
return 0;
|
||||||
|
// times[0] is current open bar time; last closed is times[1]
|
||||||
|
return times[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsHourInRange(int hr, int startHr, int endHr)
|
||||||
|
{
|
||||||
|
// Handles wrap-around (e.g., 22 -> 6)
|
||||||
|
if (startHr <= endHr)
|
||||||
|
return (hr >= startHr && hr < endHr);
|
||||||
|
else
|
||||||
|
return (hr >= startHr || hr < endHr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetXKIStateAndKI(string symbol, ENUM_TIMEFRAMES tf, int shift, int &stateOut, double &kiOut)
|
||||||
|
{
|
||||||
|
// Prepare indicator handle for this TF
|
||||||
|
static int handleH1 = INVALID_HANDLE;
|
||||||
|
static int handleH4 = INVALID_HANDLE;
|
||||||
|
static int handleD1 = INVALID_HANDLE;
|
||||||
|
|
||||||
|
int handleRef = handleH1;
|
||||||
|
if (tf == PERIOD_H4)
|
||||||
|
handleRef = handleH4;
|
||||||
|
else if (tf == PERIOD_D1)
|
||||||
|
handleRef = handleD1;
|
||||||
|
|
||||||
|
if (handleRef == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
handleRef = iCustom(symbol, tf, g_xkiIndicatorPath,
|
||||||
|
InpKiLength, InpShowKI, InpCalcLastBars);
|
||||||
|
if (handleRef == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
Print("Failed to create XKI handle for TF: ", EnumToString(tf));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double kiBuff[];
|
||||||
|
double stateBuff[];
|
||||||
|
|
||||||
|
if (CopyBuffer(handleRef, KI_BUFFER_INDEX, shift, 1, kiBuff) != 1)
|
||||||
|
return false;
|
||||||
|
if (CopyBuffer(handleRef, KI_STATE_BUFFER_INDEX, shift, 1, stateBuff) != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
kiOut = kiBuff[0];
|
||||||
|
stateOut = (int)stateBuff[0];
|
||||||
|
|
||||||
|
if (!MathIsValidNumber(kiOut))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HigherTFAgrees(string symbol, ENUM_TIMEFRAMES tf, int shift, int signalState)
|
||||||
|
{
|
||||||
|
int stateHTF;
|
||||||
|
double kiHTF;
|
||||||
|
if (!GetXKIStateAndKI(symbol, tf, shift, stateHTF, kiHTF))
|
||||||
|
return false;
|
||||||
|
if (signalState == BULLISH_STATE)
|
||||||
|
return (stateHTF == BULLISH_STATE);
|
||||||
|
if (signalState == BEARISH_STATE)
|
||||||
|
return (stateHTF == BEARISH_STATE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasOpenPosition(string symbol, int magic)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < PositionsTotal(); i++)
|
||||||
|
{
|
||||||
|
ulong ticket = PositionGetTicket(i);
|
||||||
|
if (ticket == 0)
|
||||||
|
continue;
|
||||||
|
if (PositionSelectByTicket(ticket))
|
||||||
|
{
|
||||||
|
string sym = PositionGetString(POSITION_SYMBOL);
|
||||||
|
long mg = (long)PositionGetInteger(POSITION_MAGIC);
|
||||||
|
if (sym == symbol && mg == magic)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaceOrder(string symbol, ENUM_ORDER_TYPE type, double lots, double sl, double tp)
|
||||||
|
{
|
||||||
|
MqlTradeRequest req;
|
||||||
|
MqlTradeResult res;
|
||||||
|
ZeroMemory(req);
|
||||||
|
ZeroMemory(res);
|
||||||
|
|
||||||
|
double price = 0.0;
|
||||||
|
if (!SymbolInfoTick(symbol, g_tick))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (type == ORDER_TYPE_BUY)
|
||||||
|
price = g_tick.ask;
|
||||||
|
else if (type == ORDER_TYPE_SELL)
|
||||||
|
price = g_tick.bid;
|
||||||
|
|
||||||
|
// Normalize SL/TP
|
||||||
|
sl = NormalizeDouble(sl, g_digits);
|
||||||
|
tp = NormalizeDouble(tp, g_digits);
|
||||||
|
price = NormalizeDouble(price, g_digits);
|
||||||
|
|
||||||
|
req.action = TRADE_ACTION_DEAL;
|
||||||
|
req.symbol = symbol;
|
||||||
|
req.volume = lots;
|
||||||
|
req.type = type;
|
||||||
|
req.price = price;
|
||||||
|
req.sl = sl;
|
||||||
|
req.tp = tp;
|
||||||
|
req.deviation = InpSlippagePoints;
|
||||||
|
req.magic = InpMagic;
|
||||||
|
req.comment = InpOrderComment;
|
||||||
|
|
||||||
|
if (!OrderSend(req, res))
|
||||||
|
Print("OrderSend failed: ", res.retcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrailStopsByKI()
|
||||||
|
{
|
||||||
|
// Trail per position using current signal TF KI
|
||||||
|
for (int i = 0; i < PositionsTotal(); i++)
|
||||||
|
{
|
||||||
|
ulong ticket = PositionGetTicket(i);
|
||||||
|
if (ticket == 0)
|
||||||
|
continue;
|
||||||
|
if (!PositionSelectByTicket(ticket))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string sym = PositionGetString(POSITION_SYMBOL);
|
||||||
|
long mg = (long)PositionGetInteger(POSITION_MAGIC);
|
||||||
|
if (sym != InpSymbol || mg != InpMagic)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ENUM_POSITION_TYPE ptype = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||||
|
double sl = PositionGetDouble(POSITION_SL);
|
||||||
|
double priceOpen = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||||
|
|
||||||
|
// Use last closed bar KI for stability
|
||||||
|
int shift = 1;
|
||||||
|
int state;
|
||||||
|
double ki;
|
||||||
|
if (!GetXKIStateAndKI(sym, InpSignalTF, shift, state, ki))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MqlTradeRequest req;
|
||||||
|
MqlTradeResult res;
|
||||||
|
ZeroMemory(req);
|
||||||
|
ZeroMemory(res);
|
||||||
|
|
||||||
|
double newSL = sl;
|
||||||
|
|
||||||
|
if (ptype == POSITION_TYPE_BUY)
|
||||||
|
{
|
||||||
|
double proposedSL = NormalizeDouble(ki, g_digits);
|
||||||
|
if (proposedSL > sl)
|
||||||
|
newSL = proposedSL; // only move up
|
||||||
|
}
|
||||||
|
else if (ptype == POSITION_TYPE_SELL)
|
||||||
|
{
|
||||||
|
double proposedSL = NormalizeDouble(ki, g_digits);
|
||||||
|
if (proposedSL < sl || sl == 0.0)
|
||||||
|
newSL = proposedSL; // only move down (or set if none)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newSL != sl && newSL != 0.0)
|
||||||
|
{
|
||||||
|
req.action = TRADE_ACTION_SLTP;
|
||||||
|
req.symbol = sym;
|
||||||
|
req.sl = newSL;
|
||||||
|
req.tp = PositionGetDouble(POSITION_TP);
|
||||||
|
req.magic = InpMagic;
|
||||||
|
|
||||||
|
if (!OrderSend(req, res))
|
||||||
|
Print("Trail SLTP failed: ", res.retcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
///////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SaherElm IT Center MQL5 Expert Advisor
|
||||||
|
// -------------------------------------------------
|
||||||
|
// Name: X121XKIEA
|
||||||
|
// Description: Base Expert Advisor as Template ...
|
||||||
|
//
|
||||||
|
// Maintainer:
|
||||||
|
// ------------
|
||||||
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Global Properties ...
|
||||||
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
||||||
|
#property link "https://saherelm.ir"
|
||||||
|
#property version "1.00"
|
||||||
|
#property icon "../Images/SaherElm_Logo_Color.ico"
|
||||||
|
#property description "SaherElm XFIMA Expert Advisor"
|
||||||
|
#property strict
|
||||||
|
|
||||||
|
//
|
||||||
|
#define ShortName "X121XKIEA"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Importts ...
|
||||||
|
#include "../X121XKIEA/Classes/x-saherelm.x121xki.expert.class.mq5"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Inputs ...
|
||||||
|
|
||||||
|
//#region Inputs ...
|
||||||
|
//#endregion
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -8,7 +8,8 @@
|
|||||||
"C_Cpp.default.includePath": [
|
"C_Cpp.default.includePath": [
|
||||||
"c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Include\\Include",
|
"c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Include\\Include",
|
||||||
"c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Include",
|
"c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Include",
|
||||||
"c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\572C4A1F743028C65C8BA0B780030F0D\\MQL5\\Include"
|
"c:\\Users\\SaherElm\\AppData\\Roaming\\MetaQuotes\\Terminal\\572C4A1F743028C65C8BA0B780030F0D\\MQL5\\Include",
|
||||||
|
"c:\\Users\\saherelm\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Include"
|
||||||
],
|
],
|
||||||
"C_Cpp.clang_format_style": "{ BasedOnStyle: Microsoft, UseTab: Never, IndentWidth: 4, TabWidth: 4, ColumnLimit: 0}",
|
"C_Cpp.clang_format_style": "{ BasedOnStyle: Microsoft, UseTab: Never, IndentWidth: 4, TabWidth: 4, ColumnLimit: 0}",
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
|
|||||||
Reference in New Issue
Block a user