//+------------------------------------------------------------------+
//| SmartFlow Sniper v3.5 (TWIN & FIXED) - FINAL ERROR FREE |
//| Fix: Added missing atr_trend declaration & verified inputs |
//| Features: Fixed Lot, Twin Trading, Basket Profit, Clean Code |
//+------------------------------------------------------------------+
#property strict
#property version "3.5"
#property copyright "© SmartFlow Sniper"
#property description "Ultimate Version with Twin Trading & Fixed Lot"
#include <Trade\[Link]>
#include <Trade\[Link]>
#include <Trade\[Link]>
#include <Trade\[Link]>
// --- ENUMERATIONS ---
enum ENUM_TRADE_DIRECTION { TRADE_BOTH, TRADE_BUY_ONLY, TRADE_SELL_ONLY };
enum ENUM_LOT_MODE { LOT_DYNAMIC_RISK, LOT_FIXED };
//+------------------------------------------------------------------+
//| PARAMETER INPUT |
//+------------------------------------------------------------------+
input group "=== GENERAL SETTINGS ==="
input ulong InpMagicNumber = 20251122;
input string InpTradeComment = "SmartFlow-Twin";
input bool InpEnableMultiPair = true;
input string InpTradePairs = "XAUUSD,EURUSD,GBPUSD,USDJPY";
input ENUM_TRADE_DIRECTION InpTradeDirection = TRADE_BOTH;
// --- LOT & MONEY MANAGEMENT ---
input group "=== LOT & MONEY MANAGEMENT ==="
input ENUM_LOT_MODE InpLotMode = LOT_FIXED; // Fixed Lot atau Dynamic
input double InpFixedLotSize = 0.01; // Besar Lot (Fixed Mode)
input double InpRiskPercent = 1.0; // Risk % (Dynamic Mode)
input double InpMaxLotPerTrade = 5.0;
// --- EQUITY PROTECTION ---
input bool InpUseEquityProtection = true;
input double InpEquityMinPercent = 70.0;
// --- TWIN TRADING ---
input group "=== TWIN TRADING STRATEGY ==="
input bool InpUseTwinEntry = true; // Open 2 Posisi (0.01 + 0.01)
input double InpTwinTP1Multiplier = 1.0; // TP Order 1 (x SL)
input double InpTwinTP2Multiplier = 3.0; // TP Order 2 (x SL)
input group "=== GLOBAL BASKET PROFIT ==="
input bool InpUseBasketProfit = true;
input double InpBasketTargetUSD = 50.0;
input bool InpUseBasketPercent = false;
input double InpBasketTargetPercent= 1.0;
input group "=== TRADING HOURS ==="
input bool InpEnableTradingHours = true;
input int InpStartHour = 8;
input int InpEndHour = 22;
input group "=== STRATEGY & INDICATORS ==="
input int InpMAFastPeriod = 12;
input int InpMASlowPeriod = 26;
input int InpMATrendPeriod = 50;
input int InpMATrendSlowPeriod = 200;
input ENUM_MA_METHOD InpMAMethod = MODE_EMA;
input int InpRSIPeriod = 14;
input double InpRSIOverbought = 65.0;
input double InpRSIOversold = 35.0;
input bool InpUseADXFilter = true;
input int InpADXPeriod = 14;
input double InpMinADXLevel = 20.0;
input int InpATRPeriod = 14;
input double InpATRMultiplier = 2.0;
input double InpRiskRewardRatio = 2.5;
input bool InpUseCandleConfirm = true;
input double InpMinCandleBody = 0.0;
//+------------------------------------------------------------------+
//| PAIR SPECIFIC SETTINGS |
//+------------------------------------------------------------------+
input group "=== BREAKEVEN MASTER ==="
input bool InpEnableBreakeven = true;
input group "=== XAUUSD (GOLD) SETTINGS ==="
input int InpGoldMinSLPoints = 400;
input double InpGoldATRMultiplier = 1.5;
input int InpGoldBEPoints = 350;
input int InpGoldBELock = 50;
input group "=== FOREX MAJORS SETTINGS ==="
input int InpForexMinSLPoints = 200;
input double InpForexATRMultiplier= 2.0;
input int InpForexBEPoints = 200;
input int InpForexBELock = 20;
input group "=== USDJPY SETTINGS ==="
input int InpUSDJPYMinSLPoints = 200;
input double InpUSDJPYATRMultiplier = 2.0;
input int InpUSDJPYBEPoints = 150;
input int InpUSDJPYBELock = 20;
//+------------------------------------------------------------------+
//| TRAILING & EXIT |
//+------------------------------------------------------------------+
input group "=== TRAILING & ENTRY ==="
input bool InpEnableTrailingStop = true;
input double InpTrailingATRMultiplier = 2.5;
input int InpTrailingStartPoints = 150;
input bool InpUsePullbackEntry = true;
input int InpPullbackDepth = 25;
input ENUM_TIMEFRAMES InpTrendTF = PERIOD_H4;
input ENUM_TIMEFRAMES InpEntryTF = PERIOD_M15;
input group "=== ADVANCED SETTINGS ==="
input int InpMaxOpenPositions = 10;
input int InpMaxSlippage = 10;
input bool InpEnableDebug = true;
//+------------------------------------------------------------------+
//| GLOBAL VARIABLES & STRUCTS |
//+------------------------------------------------------------------+
CTrade trade;
CPositionInfo position;
string g_pairs[];
struct PairIndicators
{
string symbol;
int h_ma_fast;
int h_ma_slow;
int h_ma_trend;
int h_ma_trend_slow;
int h_rsi;
int h_adx;
int h_atr;
int h_atr_trend;
};
PairIndicators g_indicators[];
double g_floatingProfit = 0.0;
//+------------------------------------------------------------------+
//| INISIALISASI INDIKATOR |
//+------------------------------------------------------------------+
bool InitIndicators()
{
int totalPairs = ArraySize(g_pairs);
ArrayResize(g_indicators, totalPairs);
for(int i=0; i<totalPairs; i++)
{
g_indicators[i].symbol = g_pairs[i];
g_indicators[i].h_ma_fast = iMA(g_pairs[i], InpEntryTF, InpMAFastPeriod, 0,
InpMAMethod, PRICE_CLOSE);
g_indicators[i].h_ma_slow = iMA(g_pairs[i], InpEntryTF, InpMASlowPeriod, 0,
InpMAMethod, PRICE_CLOSE);
g_indicators[i].h_ma_trend = iMA(g_pairs[i], InpTrendTF, InpMATrendPeriod, 0,
InpMAMethod, PRICE_CLOSE);
g_indicators[i].h_ma_trend_slow = iMA(g_pairs[i], InpTrendTF,
InpMATrendSlowPeriod, 0, InpMAMethod, PRICE_CLOSE);
g_indicators[i].h_rsi = iRSI(g_pairs[i], InpEntryTF, InpRSIPeriod,
PRICE_CLOSE);
g_indicators[i].h_adx = iADX(g_pairs[i], InpEntryTF, InpADXPeriod);
g_indicators[i].h_atr = iATR(g_pairs[i], InpEntryTF, InpATRPeriod);
g_indicators[i].h_atr_trend = iATR(g_pairs[i], InpTrendTF, InpATRPeriod);
if(g_indicators[i].h_ma_fast == INVALID_HANDLE) return false;
}
return true;
}
double GetIndicatorVal(int handle, int buffer, int index)
{
double arr[];
ArraySetAsSeries(arr, true);
if(CopyBuffer(handle, buffer, index, 1, arr) < 0) return 0.0;
return arr[0];
}
//+------------------------------------------------------------------+
//| HELPER: PRICE ACTION CHECK |
//+------------------------------------------------------------------+
bool IsCandleBullish(string symbol, ENUM_TIMEFRAMES tf, int index)
{
double open[], close[];
ArraySetAsSeries(open, true); ArraySetAsSeries(close, true);
CopyOpen(symbol, tf, index, 1, open); CopyClose(symbol, tf, index, 1, close);
bool isGreen = close[0] > open[0];
double body = MathAbs(close[0] - open[0]) / SymbolInfoDouble(symbol,
SYMBOL_POINT);
return (isGreen && body >= InpMinCandleBody);
}
bool IsCandleBearish(string symbol, ENUM_TIMEFRAMES tf, int index)
{
double open[], close[];
ArraySetAsSeries(open, true); ArraySetAsSeries(close, true);
CopyOpen(symbol, tf, index, 1, open); CopyClose(symbol, tf, index, 1, close);
bool isRed = close[0] < open[0];
double body = MathAbs(close[0] - open[0]) / SymbolInfoDouble(symbol,
SYMBOL_POINT);
return (isRed && body >= InpMinCandleBody);
}
double GetClosePrice(string symbol, ENUM_TIMEFRAMES tf, int index)
{
double close[]; ArraySetAsSeries(close, true);
CopyClose(symbol, tf, index, 1, close);
return close[0];
}
//+------------------------------------------------------------------+
//| ANALISIS SINYAL |
//+------------------------------------------------------------------+
struct SignalResult { bool valid; int direction; double sl_dist; string comment; };
struct PairSettings { double minSLPoints; double atrMultiplier; int bePoints; int
beLock; };
PairSettings GetPairConfig(string symbol)
{
PairSettings cfg;
if(symbol == "XAUUSD") {
[Link] = InpGoldMinSLPoints; [Link] =
InpGoldATRMultiplier;
[Link] = InpGoldBEPoints; [Link] = InpGoldBELock;
} else if(symbol == "USDJPY") {
[Link] = InpUSDJPYMinSLPoints; [Link] =
InpUSDJPYATRMultiplier;
[Link] = InpUSDJPYBEPoints; [Link] = InpUSDJPYBELock;
} else {
[Link] = InpForexMinSLPoints; [Link] =
InpForexATRMultiplier;
[Link] = InpForexBEPoints; [Link] = InpForexBELock;
}
return cfg;
}
SignalResult AnalyzeMarket(int pairIndex)
{
SignalResult res = {false, 0, 0.0, ""};
string symbol = g_pairs[pairIndex];
double ma_fast_m15 = GetIndicatorVal(g_indicators[pairIndex].h_ma_fast, 0, 1);
double ma_slow_m15 = GetIndicatorVal(g_indicators[pairIndex].h_ma_slow, 0, 1);
double ma_trend_h4 = GetIndicatorVal(g_indicators[pairIndex].h_ma_trend, 0, 1);
double ma_trend_slow_h4 =
GetIndicatorVal(g_indicators[pairIndex].h_ma_trend_slow, 0, 1);
double rsi = GetIndicatorVal(g_indicators[pairIndex].h_rsi, 0, 1);
double adx = GetIndicatorVal(g_indicators[pairIndex].h_adx, 0, 1);
double atr = GetIndicatorVal(g_indicators[pairIndex].h_atr, 0, 0);
// FIX: Added declared atr_trend for Advanced Filter
double atr_trend = GetIndicatorVal(g_indicators[pairIndex].h_atr_trend, 0, 0);
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
if(InpUseADXFilter && adx < InpMinADXLevel) return res;
if(InpUseAdvancedFilter) {
if(atr_trend / bid < InpMinVolatility) return res;
}
PairSettings cfg = GetPairConfig(symbol);
double sl_dist = MathMax([Link] * point, atr * [Link]);
res.sl_dist = sl_dist;
// --- LOGIC BUY ---
if(InpTradeDirection != TRADE_SELL_ONLY)
{
if(ma_trend_h4 > ma_trend_slow_h4 && ma_fast_m15 > ma_slow_m15)
{
if(rsi > InpRSIOversold && rsi < InpRSIOverbought)
{
bool pa_confirm = true;
if(InpUseCandleConfirm) {
if(!IsCandleBullish(symbol, InpEntryTF, 1)) pa_confirm = false;
if(GetClosePrice(symbol, InpEntryTF, 1) < ma_fast_m15) pa_confirm =
false;
}
if(pa_confirm) {
bool pullback_ok = true;
if(InpUsePullbackEntry) {
double max_dist = InpPullbackDepth * point;
if((bid - ma_fast_m15) > max_dist) pullback_ok = false;
}
if(pullback_ok) {
[Link] = true; [Link] = 1; [Link] = "Buy Signal
(Twin)"; return res;
}
}
}
}
}
// --- LOGIC SELL ---
if(InpTradeDirection != TRADE_BUY_ONLY)
{
if(ma_trend_h4 < ma_trend_slow_h4 && ma_fast_m15 < ma_slow_m15)
{
if(rsi < InpRSIOverbought && rsi > InpRSIOversold)
{
bool pa_confirm = true;
if(InpUseCandleConfirm) {
if(!IsCandleBearish(symbol, InpEntryTF, 1)) pa_confirm = false;
if(GetClosePrice(symbol, InpEntryTF, 1) > ma_fast_m15) pa_confirm =
false;
}
if(pa_confirm) {
bool pullback_ok = true;
if(InpUsePullbackEntry) {
double max_dist = InpPullbackDepth * point;
if((ma_fast_m15 - ask) > max_dist) pullback_ok = false;
}
if(pullback_ok) {
[Link] = true; [Link] = -1; [Link] = "Sell Signal
(Twin)"; return res;
}
}
}
}
}
return res;
}
//+------------------------------------------------------------------+
//| LOT CALCULATION (FIXED OR DYNAMIC) |
//+------------------------------------------------------------------+
double GetLotSize(string symbol, double sl_dist)
{
if(InpLotMode == LOT_FIXED) {
double min_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
if(InpFixedLotSize < min_lot) return min_lot;
return InpFixedLotSize;
}
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double risk_money = equity * (InpRiskPercent / 100.0);
double tick_val = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
if(sl_dist == 0 || tick_val == 0) return 0.01;
double lot = risk_money / (sl_dist / point * tick_val);
double min_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
double step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
lot = MathFloor(lot / step) * step;
if(lot < min_lot) lot = min_lot;
if(lot > InpMaxLotPerTrade) lot = InpMaxLotPerTrade;
return lot;
}
//+------------------------------------------------------------------+
//| MANAGE POSITIONS (TWIN COMPATIBLE) |
//+------------------------------------------------------------------+
void ManagePositions(int pairIndex)
{
string symbol = g_pairs[pairIndex];
double atr = GetIndicatorVal(g_indicators[pairIndex].h_atr, 0, 0);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
PairSettings cfg = GetPairConfig(symbol);
for(int i=PositionsTotal()-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) != symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
double currentTP = PositionGetDouble(POSITION_TP);
long type = PositionGetInteger(POSITION_TYPE);
double currentPrice = (type == POSITION_TYPE_BUY) ? SymbolInfoDouble(symbol,
SYMBOL_BID) : SymbolInfoDouble(symbol, SYMBOL_ASK);
// BREAKEVEN Logic
if(InpEnableBreakeven) {
double profitPoints = (type == POSITION_TYPE_BUY) ? (currentPrice -
openPrice)/point : (openPrice - currentPrice)/point;
if(profitPoints >= [Link]) {
double newSL = 0; bool modify = false;
if(type == POSITION_TYPE_BUY) { newSL = openPrice + ([Link] *
point); if(newSL > currentSL) modify = true; }
else { newSL = openPrice - ([Link] * point); if(currentSL == 0 ||
newSL < currentSL) modify = true; }
if(modify) [Link](ticket, newSL, currentTP);
}
}
// TRAILING STOP Logic
if(InpEnableTrailingStop) {
double trailDist = atr * InpTrailingATRMultiplier;
double profitPoints = (type == POSITION_TYPE_BUY) ? (currentPrice -
openPrice)/point : (openPrice - currentPrice)/point;
if(profitPoints >= InpTrailingStartPoints) {
double newSL = 0; bool modify = false;
if(type == POSITION_TYPE_BUY) { newSL = currentPrice - trailDist;
if(newSL > currentSL && newSL > openPrice) modify = true; }
else { newSL = currentPrice + trailDist; if((currentSL == 0 || newSL <
currentSL) && newSL < openPrice) modify = true; }
if(modify) [Link](ticket, newSL, currentTP);
}
}
}
}
void CheckBasketProfit()
{
if(!InpUseBasketProfit) return;
double totalProfit = 0.0; int posCount = 0;
for(int i=PositionsTotal()-1; i>=0; i--) {
if(PositionSelectByTicket(PositionGetTicket(i))) {
if(PositionGetInteger(POSITION_MAGIC) == InpMagicNumber) {
totalProfit += PositionGetDouble(POSITION_PROFIT);
totalProfit += PositionGetDouble(POSITION_SWAP);
posCount++;
}
}
}
g_floatingProfit = totalProfit;
double target = InpBasketTargetUSD;
if(InpUseBasketPercent) target = AccountInfoDouble(ACCOUNT_BALANCE) *
(InpBasketTargetPercent / 100.0);
if(posCount > 0 && totalProfit >= target) {
Print("💰 BASKET TARGET REACHED! Profit: $", DoubleToString(totalProfit, 2));
for(int i=PositionsTotal()-1; i>=0; i--) {
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_MAGIC)
== InpMagicNumber) [Link](ticket); }
}
}
}
void ScanTradeHistory()
{
if(TimeCurrent() - g_lastHistoryCheck < 10 && g_lastHistoryCheck != 0) return;
HistorySelect(g_lastHistoryCheck, TimeCurrent());
int deals = HistoryDealsTotal();
for(int i = 0; i < deals; i++) {
ulong ticket = HistoryDealGetTicket(i);
if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT) {
if(HistoryDealGetInteger(ticket, DEAL_MAGIC) == InpMagicNumber) {
double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
g_totalTrades++;
if(profit > 0) { g_winningTrades++; g_consecutiveLosses = 0; } else
{ g_consecutiveLosses++; }
}
}
}
g_lastHistoryCheck = TimeCurrent();
}
double CalculateDynamicRisk()
{
if(!InpLotMode == LOT_DYNAMIC_RISK) return InpFixedLotSize;
double winRate = (g_totalTrades > 0) ? (double)g_winningTrades / g_totalTrades *
100.0 : 0;
double risk = InpRiskPercent;
// Simple dynamic logic if needed, else just return InpRiskPercent
return risk;
}
void UpdateDashboard()
{
string text = "=== SMARTFLOW SNIPER v3.5 (TWIN) ===\n";
text += "Equity: " + DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2) + "\
n";
text += "Open Pos: " + IntegerToString(PositionsTotal()) + "/" +
IntegerToString(InpMaxOpenPositions) + "\n";
text += "Global Floating: " + DoubleToString(g_floatingProfit, 2) + " USD\n";
string dir = "BOTH"; if(InpTradeDirection == TRADE_BUY_ONLY) dir = "BUY ONLY";
if(InpTradeDirection == TRADE_SELL_ONLY) dir = "SELL ONLY";
text += "Mode: " + dir + "\n";
string lotmode = (InpLotMode == LOT_FIXED) ? "FIXED
("+DoubleToString(InpFixedLotSize,2)+")" : "DYNAMIC
("+DoubleToString(InpRiskPercent,1)+"%)";
text += "Lot Mode: " + lotmode + "\n";
if(InpUseTwinEntry) text += "Strategy: TWIN ENTRY (2x Exec)\n";
Comment(text);
}
int OnInit()
{
[Link](InpMagicNumber);
[Link](InpMaxSlippage);
StringSplit(InpTradePairs, ',', g_pairs);
for(int i=0; i<ArraySize(g_pairs); i++) { StringTrimLeft(g_pairs[i]);
StringTrimRight(g_pairs[i]); }
if(!InitIndicators()) return INIT_FAILED;
Print("=== SMARTFLOW SNIPER v3.5 (TWIN EDITION) INITIALIZED ===");
return INIT_SUCCEEDED;
}
void OnTick()
{
CheckBasketProfit(); UpdateDashboard();
ScanTradeHistory();
if(InpUseEquityProtection) { if(AccountInfoDouble(ACCOUNT_EQUITY) <
AccountInfoDouble(ACCOUNT_BALANCE) * (InpEquityMinPercent/100.0)) return; }
if(InpEnableTradingHours) { MqlDateTime dt; TimeCurrent(dt); if([Link] <
InpStartHour || [Link] > InpEndHour) return; }
int totalPositions = PositionsTotal();
for(int i=0; i<ArraySize(g_pairs); i++)
{
string symbol = g_pairs[i];
if(!SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE)) continue;
ManagePositions(i);
bool alreadyOpen = false;
for(int p=0; p<totalPositions; p++) {
if(PositionGetSymbol(p) == symbol && PositionGetInteger(POSITION_MAGIC) ==
InpMagicNumber) { alreadyOpen = true; break; }
}
if(alreadyOpen) continue;
if(totalPositions >= InpMaxOpenPositions) continue;
SignalResult sig = AnalyzeMarket(i);
if([Link]) {
double lot = GetLotSize(symbol, sig.sl_dist);
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
double sl = ([Link] == 1) ? bid - sig.sl_dist : ask + sig.sl_dist;
if(InpUseTwinEntry)
{
double tp1 = ([Link] == 1) ? bid + (sig.sl_dist *
InpTwinTP1Multiplier) : ask - (sig.sl_dist * InpTwinTP1Multiplier);
if([Link] == 1) [Link](lot, symbol, 0, sl, tp1,
InpTradeComment + "-1");
else [Link](lot, symbol, 0, sl, tp1, InpTradeComment + "-1");
double tp2 = ([Link] == 1) ? bid + (sig.sl_dist *
InpTwinTP2Multiplier) : ask - (sig.sl_dist * InpTwinTP2Multiplier);
if([Link] == 1) [Link](lot, symbol, 0, sl, tp2,
InpTradeComment + "-2");
else [Link](lot, symbol, 0, sl, tp2, InpTradeComment + "-2");
Print("✅ Twin Order Executed: ", symbol, " | Vol: ", lot, "x2");
}
else
{
double tp = ([Link] == 1) ? bid + (sig.sl_dist *
InpRiskRewardRatio) : ask - (sig.sl_dist * InpRiskRewardRatio);
if([Link] == 1) [Link](lot, symbol, 0, sl, tp,
InpTradeComment);
else [Link](lot, symbol, 0, sl, tp, InpTradeComment);
Print("✅ Single Order Executed: ", symbol, " | Vol: ", lot);
}
}
}
}
void OnDeinit(const int reason)
{
Comment("");
for(int i=0; i<ArraySize(g_indicators); i++) {
IndicatorRelease(g_indicators[i].h_ma_fast);
IndicatorRelease(g_indicators[i].h_ma_slow);
IndicatorRelease(g_indicators[i].h_atr);
IndicatorRelease(g_indicators[i].h_rsi); IndicatorRelease(g_indicators[i].h_adx);
}
}