The 5-Minute Chart: The Scalper's Middle Ground
Re: The 5-Minute Chart: The Scalper's Middle Ground
How it executes your philosophy:
The 200 EMA (Thick White Line): Acts as the primary filter. If price is above it, the script ignores all bearish signals. If below, it ignores all bullish signals. This stops you from taking impulsive trades against the dominant momentum.
The 9/21 EMA Cross (Blue/Orange Lines): This provides the "multiple legitimate setups" per session. It lags slightly behind a 1-minute chart, meaning a cross on the 5-minute actually represents confirmed momentum rather than a 30-second fakeout.
ATR Risk Management: By using Average True Range to set targets, the script forces mechanical, thoughtful trade management (a default 1:2 Risk-to-Reward) instead of panic-closing a trade because a 1-minute candle flashed red.
The 200 EMA (Thick White Line): Acts as the primary filter. If price is above it, the script ignores all bearish signals. If below, it ignores all bullish signals. This stops you from taking impulsive trades against the dominant momentum.
The 9/21 EMA Cross (Blue/Orange Lines): This provides the "multiple legitimate setups" per session. It lags slightly behind a 1-minute chart, meaning a cross on the 5-minute actually represents confirmed momentum rather than a 30-second fakeout.
ATR Risk Management: By using Average True Range to set targets, the script forces mechanical, thoughtful trade management (a default 1:2 Risk-to-Reward) instead of panic-closing a trade because a 1-minute candle flashed red.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
To elevate this script from a "beginner's template" to a professional-grade scalping tool, we need to add the mechanics that full-time traders actually use to survive in live markets.
A professional strategy doesn't just look for entries; it focuses heavily on capital preservation, filtering out "chop" (sideways markets), and scaling out of trades.
What makes this version "Pro"?
Dynamic Risk-Based Position Sizing: Instead of using an arbitrary percentage of your account, it calculates your exact lot/position size so you only ever risk exactly 1% (or your chosen amount) of your capital per trade.
The "Chop" Filter (ADX): EMA crosses happen constantly in sideways markets, leading to death by a thousand paper cuts. This version adds the Average Directional Index (ADX) to ensure there is actual momentum before taking a signal.
Partial Take Profits & Breakeven: It automatically sells 50% of your position at a 1:1 risk/reward (TP1) to secure profits, then moves your Stop Loss to breakeven, letting the remaining 50% run "risk-free" to a 1:2 target (TP2).
Session Constraints: Pros don't scalp 24/7. This script restricts trading to high-liquidity hours (e.g., the New York overlap) to avoid low-volume fakeouts.
Heads-Up Display (HUD): A real-time dashboard on your chart showing market state, current ATR, and trend conditions.
A professional strategy doesn't just look for entries; it focuses heavily on capital preservation, filtering out "chop" (sideways markets), and scaling out of trades.
What makes this version "Pro"?
Dynamic Risk-Based Position Sizing: Instead of using an arbitrary percentage of your account, it calculates your exact lot/position size so you only ever risk exactly 1% (or your chosen amount) of your capital per trade.
The "Chop" Filter (ADX): EMA crosses happen constantly in sideways markets, leading to death by a thousand paper cuts. This version adds the Average Directional Index (ADX) to ensure there is actual momentum before taking a signal.
Partial Take Profits & Breakeven: It automatically sells 50% of your position at a 1:1 risk/reward (TP1) to secure profits, then moves your Stop Loss to breakeven, letting the remaining 50% run "risk-free" to a 1:2 target (TP2).
Session Constraints: Pros don't scalp 24/7. This script restricts trading to high-liquidity hours (e.g., the New York overlap) to avoid low-volume fakeouts.
Heads-Up Display (HUD): A real-time dashboard on your chart showing market state, current ATR, and trend conditions.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
The Pro 5-Minute Scalper (Pine Script v5)
Code: Select all
//@version=5
strategy("Pro 5-Min Sweet Spot Scalper", overlay=true, initial_capital=10000, commission_type=strategy.commission.percent, commission_value=0.02, calc_on_every_tick=true)
// =========================================================================
// 1. INPUTS: Pro Trade Desk Settings
// =========================================================================
grpRisk = "1. Risk Management & Sizing"
riskPct = input.float(1.0, title="Risk Per Trade (%)", group=grpRisk, tooltip="Calculates position size to strictly risk this % of your equity.")
atrLen = input.int(14, title="ATR Length", group=grpRisk)
slMult = input.float(1.5, title="Stop Loss ATR Multiplier", step=0.1, group=grpRisk)
tp1Mult = input.float(1.5, title="TP1 (Scale Out 50%) ATR", step=0.1, group=grpRisk)
tp2Mult = input.float(3.0, title="TP2 (Runner) ATR", step=0.1, group=grpRisk)
grpTime = "2. Session Constraints"
useTime = input.bool(true, title="Enable Session Filter?", group=grpTime)
tradeTime = input.session("0930-1530", title="Trading Hours (Exchange Time)", group=grpTime)
grpTrend = "3. Trend & Momentum Filters"
fastLen = input.int(9, title="Fast EMA", group=grpTrend)
slowLen = input.int(21, title="Slow EMA", group=grpTrend)
trendLen = input.int(200, title="200 EMA (Macro Trend)", group=grpTrend)
adxThresh = input.int(20, title="ADX Minimum (Chop Filter)", group=grpTrend, tooltip="Requires ADX to be above this number. Filters out sideways, choppy markets.")
// =========================================================================
// 2. INDICATORS & FILTERS
// =========================================================================
fastEma = ta.ema(close, fastLen)
slowEma = ta.ema(close, slowLen)
macroTrend = ta.ema(close, trendLen)
atr = ta.atr(atrLen)
// ADX Calculation for Chop Filter
[diPlus, diMinus, adx] = ta.dmi(14, 14)
isTrending = adx > adxThresh
// Session Filter Logic
inSession = useTime ? not na(time(timeframe.period, tradeTime)) : true
// Plotting
plot(fastEma, color=color.new(color.blue, 0), title="9 EMA", linewidth=1)
plot(slowEma, color=color.new(color.orange, 0), title="21 EMA", linewidth=1)
plot(macroTrend, color=color.new(color.white, 0), title="200 EMA", linewidth=2)
// =========================================================================
// 3. EXECUTION LOGIC & POSITION SIZING
// =========================================================================
longSignal = ta.crossover(fastEma, slowEma) and close > macroTrend and isTrending and inSession
shortSignal = ta.crossunder(fastEma, slowEma) and close < macroTrend and isTrending and inSession
// Persistent variables for dynamic trade management
var float entryPrice = na
var float slPrice = na
var float tp1Price = na
var float tp2Price = na
var bool tp1Hit = false
// Position Sizing Math (Risk % / Stop Loss Distance)
riskAmount = (strategy.equity * riskPct) / 100
slDistance = atr * slMult
tradeQty = slDistance > 0 ? (riskAmount / slDistance) : 0
if (longSignal and strategy.position_size == 0)
entryPrice := close
slPrice := close - slDistance
tp1Price := close + (atr * tp1Mult)
tp2Price := close + (atr * tp2Mult)
tp1Hit := false
strategy.entry("Long", strategy.long, qty=tradeQty)
if (shortSignal and strategy.position_size == 0)
entryPrice := close
slPrice := close + slDistance
tp1Price := close - (atr * tp1Mult)
tp2Price := close - (atr * tp2Mult)
tp1Hit := false
strategy.entry("Short", strategy.short, qty=tradeQty)
// =========================================================================
// 4. ADVANCED TRADE MANAGEMENT (Scale-outs & Breakeven)
// =========================================================================
if (strategy.position_size > 0)
// Check if TP1 is hit to trigger breakeven
if high >= tp1Price
tp1Hit := true
// If TP1 is hit, SL moves to Entry. Otherwise, it stays at original SL.
activeSL = tp1Hit ? entryPrice : slPrice
// Manage Exits
strategy.exit("TP1", "Long", qty_percent=50, limit=tp1Price, stop=activeSL)
strategy.exit("TP2", "Long", limit=tp2Price, stop=activeSL)
if (strategy.position_size < 0)
if low <= tp1Price
tp1Hit := true
activeSL = tp1Hit ? entryPrice : slPrice
strategy.exit("TP1", "Short", qty_percent=50, limit=tp1Price, stop=activeSL)
strategy.exit("TP2", "Short", limit=tp2Price, stop=activeSL)
// =========================================================================
// 5. VISUAL SIGNALS & HUD DASHBOARD
// =========================================================================
plotshape(series=longSignal and strategy.position_size == 0, title="Long Entry", location=location.belowbar, color=color.green, style=shape.labelup, text="BUY", textcolor=color.white, size=size.small)
plotshape(series=shortSignal and strategy.position_size == 0, title="Short Entry", location=location.abovebar, color=color.red, style=shape.labeldown, text="SELL", textcolor=color.white, size=size.small)
// HUD (Heads Up Display)
var table hud = table.new(position.bottom_right, 2, 4, border_width=1)
if barstate.islast
table.cell(hud, 0, 0, "Macro Trend (200 EMA)", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 0, close > macroTrend ? "BULLISH" : "BEARISH", text_color=color.white, bgcolor=close > macroTrend ? color.green : color.red)
table.cell(hud, 0, 1, "Market State (ADX)", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 1, isTrending ? "TRENDING" : "CHOPPING", text_color=color.white, bgcolor=isTrending ? color.green : color.orange)
table.cell(hud, 0, 2, "Session Active", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 2, inSession ? "YES" : "NO", text_color=color.white, bgcolor=inSession ? color.green : color.red)Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
Pro-Tips for using this script:
The HUD Dashboard: Look at the bottom right of your chart. If the ADX cell says "CHOPPING" (orange), the script will intentionally ignore 9/21 crosses to save you from getting stopped out in a flat market.
Asset specific tuning: Because this uses ATR (volatility) for targets, it adapts automatically whether you are trading Forex (like EUR/USD), Indices (like NAS100), or Crypto.
Trading Hours: By default, it trades between 09:30 and 15:30. You must ensure your TradingView chart is set to the Exchange Timezone (bottom right corner of TradingView) so the hours align correctly with market open/close.
Breakeven Mechanic: You will notice on the chart that once a trade hits its first target, the strategy often exits the second half of the trade precisely at your entry price. This is the "free ride" mechanic in action—the hallmark of professional risk management.
The HUD Dashboard: Look at the bottom right of your chart. If the ADX cell says "CHOPPING" (orange), the script will intentionally ignore 9/21 crosses to save you from getting stopped out in a flat market.
Asset specific tuning: Because this uses ATR (volatility) for targets, it adapts automatically whether you are trading Forex (like EUR/USD), Indices (like NAS100), or Crypto.
Trading Hours: By default, it trades between 09:30 and 15:30. You must ensure your TradingView chart is set to the Exchange Timezone (bottom right corner of TradingView) so the hours align correctly with market open/close.
Breakeven Mechanic: You will notice on the chart that once a trade hits its first target, the strategy often exits the second half of the trade precisely at your entry price. This is the "free ride" mechanic in action—the hallmark of professional risk management.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
Translating this strategy from Pine Script (which manages virtual positions with simple functions like qty_percent) to MetaTrader's C++ based languages (MQL4/MQL5) requires an architectural shift.
MetaTrader does not have a native "close 50% of the trade at this target" command for pending orders. The professional standard to achieve this is the "Split-Position Setup": when a signal fires, the Expert Advisor (EA) opens two separate positions at half the risk. One has a Take Profit at TP1, the other has a Take Profit at TP2. A trailing loop runs in the background; when price hits TP1 distance, it moves the Stop Loss of the remaining trade to breakeven.
Here is the complete, compiled-ready code for both platforms. Note that the visual HUD has been omitted to ensure the execution engine remains lightning-fast without cluttering the MetaTrader chart objects.
MetaTrader does not have a native "close 50% of the trade at this target" command for pending orders. The professional standard to achieve this is the "Split-Position Setup": when a signal fires, the Expert Advisor (EA) opens two separate positions at half the risk. One has a Take Profit at TP1, the other has a Take Profit at TP2. A trailing loop runs in the background; when price hits TP1 distance, it moves the Stop Loss of the remaining trade to breakeven.
Here is the complete, compiled-ready code for both platforms. Note that the visual HUD has been omitted to ensure the execution engine remains lightning-fast without cluttering the MetaTrader chart objects.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
1. MetaTrader 4 (MQL4) Expert Advisor
Save this file as Pro_5Min_Scalper.mq4 in your MQL4\Experts folder.
Save this file as Pro_5Min_Scalper.mq4 in your MQL4\Experts folder.
Code: Select all
//+------------------------------------------------------------------+
//| Pro_5Min_Scalper.mq4 |
//+------------------------------------------------------------------+
#property copyright "Pro Scalper"
#property link ""
#property version "1.00"
#property strict
//--- Inputs
input double RiskPercent = 1.0; // Risk Per Trade (%)
input int ATR_Period = 14; // ATR Period
input double SL_Multiplier = 1.5; // Stop Loss ATR Multiplier
input double TP1_Multiplier = 1.5; // TP1 ATR Multiplier (Scale Out)
input double TP2_Multiplier = 3.0; // TP2 ATR Multiplier (Runner)
input int FastEMA = 9; // Fast EMA
input int SlowEMA = 21; // Slow EMA
input int TrendEMA = 200; // Macro Trend 200 EMA
input int ADX_Period = 14; // ADX Period
input double ADX_Threshold = 20.0; // ADX Chop Filter Minimum
input bool UseTimeFilter = true;
input int StartHour = 9;
input int StartMinute = 30;
input int EndHour = 15;
input int EndMinute = 30;
input int MagicNumber = 55555; // Unique EA ID
//--- Global
datetime lastBarTime = 0;
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Manage Breakeven on every tick
ManageBreakeven();
// 2. Only check for new entries on the close of a bar
if(Time[0] == lastBarTime) return;
// 3. Check Time Filter
if(UseTimeFilter && !IsTradingTime()) return;
// 4. Indicator Calculations (Shift 1 = closed bar, Shift 2 = previous closed bar)
double fast1 = iMA(_Symbol, 0, FastEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double fast2 = iMA(_Symbol, 0, FastEMA, 0, MODE_EMA, PRICE_CLOSE, 2);
double slow1 = iMA(_Symbol, 0, SlowEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double slow2 = iMA(_Symbol, 0, SlowEMA, 0, MODE_EMA, PRICE_CLOSE, 2);
double trend = iMA(_Symbol, 0, TrendEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double adx = iADX(_Symbol, 0, ADX_Period, PRICE_CLOSE, MODE_MAIN, 1);
double atr = iATR(_Symbol, 0, ATR_Period, 1);
// 5. Entry Logic
bool buySignal = (fast1 > slow1 && fast2 <= slow2) && (Close[1] > trend) && (adx > ADX_Threshold);
bool sellSignal = (fast1 < slow1 && fast2 >= slow2) && (Close[1] < trend) && (adx > ADX_Threshold);
if(buySignal && OrdersTotal() == 0) ExecuteTrade(OP_BUY, atr);
if(sellSignal && OrdersTotal() == 0) ExecuteTrade(OP_SELL, atr);
lastBarTime = Time[0];
}
//+------------------------------------------------------------------+
//| Execute Trade (Splits risk into two positions) |
//+------------------------------------------------------------------+
void ExecuteTrade(int type, double atr)
{
RefreshRates();
double entryPrice = (type == OP_BUY) ? Ask : Bid;
double slDist = atr * SL_Multiplier;
double tp1Dist = atr * TP1_Multiplier;
double tp2Dist = atr * TP2_Multiplier;
double sl = (type == OP_BUY) ? entryPrice - slDist : entryPrice + slDist;
double tp1 = (type == OP_BUY) ? entryPrice + tp1Dist : entryPrice - tp1Dist;
double tp2 = (type == OP_BUY) ? entryPrice + tp2Dist : entryPrice - tp2Dist;
// Normalize prices for broker digits
sl = NormalizeDouble(sl, _Digits);
tp1 = NormalizeDouble(tp1, _Digits);
tp2 = NormalizeDouble(tp2, _Digits);
// Calculate Lot Size (Split in half for two positions)
double totalLots = CalculateLots(slDist);
double halfLots = NormalizeDouble(totalLots / 2.0, 2);
double minLot = MarketInfo(_Symbol, MODE_MINLOT);
if(halfLots < minLot) halfLots = minLot;
// Send Split Orders
int ticket1 = OrderSend(_Symbol, type, halfLots, entryPrice, 3, sl, tp1, "ProScalp TP1", MagicNumber, 0, Blue);
int ticket2 = OrderSend(_Symbol, type, halfLots, entryPrice, 3, sl, tp2, "ProScalp TP2", MagicNumber, 0, Blue);
}
//+------------------------------------------------------------------+
//| Breakeven Management |
//+------------------------------------------------------------------+
void ManageBreakeven()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == _Symbol && OrderMagicNumber() == MagicNumber)
{
double atr = iATR(_Symbol, 0, ATR_Period, 1);
double tp1Dist = atr * TP1_Multiplier;
if(OrderType() == OP_BUY)
{
// If price reached TP1 equivalent, and SL is still below Entry
if(Bid >= OrderOpenPrice() + tp1Dist && OrderStopLoss() < OrderOpenPrice())
OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, Green);
}
else if(OrderType() == OP_SELL)
{
// If price reached TP1 equivalent, and SL is still above Entry
if(Ask <= OrderOpenPrice() - tp1Dist && (OrderStopLoss() > OrderOpenPrice() || OrderStopLoss() == 0))
OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, Green);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Utilities |
//+------------------------------------------------------------------+
bool IsTradingTime()
{
int currentHour = TimeHour(TimeCurrent());
int currentMin = TimeMinute(TimeCurrent());
int currentMins = currentHour * 60 + currentMin;
int startMins = StartHour * 60 + StartMinute;
int endMins = EndHour * 60 + EndMinute;
return (currentMins >= startMins && currentMins <= endMins);
}
double CalculateLots(double slDistance)
{
double riskAmount = AccountFreeMargin() * (RiskPercent / 100.0);
double tickValue = MarketInfo(_Symbol, MODE_TICKVALUE);
double tickSize = MarketInfo(_Symbol, MODE_TICKSIZE);
double slTicks = slDistance / tickSize;
if(slTicks <= 0 || tickValue <= 0) return MarketInfo(_Symbol, MODE_MINLOT);
double lots = riskAmount / (slTicks * tickValue);
return lots;
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
2. MetaTrader 5 (MQL5) Expert Advisor
Save this file as Pro_5Min_Scalper.mq5 in your MQL5\Experts folder. Note that MQL5 requires indicator handles setup in OnInit(). This requires a hedging account (the default for 99% of modern MT5 brokers) so you can hold two separate positions for TP1 and TP2.
Save this file as Pro_5Min_Scalper.mq5 in your MQL5\Experts folder. Note that MQL5 requires indicator handles setup in OnInit(). This requires a hedging account (the default for 99% of modern MT5 brokers) so you can hold two separate positions for TP1 and TP2.
Code: Select all
//+------------------------------------------------------------------+
//| Pro_5Min_Scalper.mq5 |
//+------------------------------------------------------------------+
#property copyright "Pro Scalper"
#property version "1.00"
#include <Trade\Trade.mqh>
//--- Inputs
input double RiskPercent = 1.0; // Risk Per Trade (%)
input int ATR_Period = 14; // ATR Period
input double SL_Multiplier = 1.5; // Stop Loss ATR Multiplier
input double TP1_Multiplier = 1.5; // TP1 ATR Multiplier (Scale Out)
input double TP2_Multiplier = 3.0; // TP2 ATR Multiplier (Runner)
input int FastEMA = 9; // Fast EMA
input int SlowEMA = 21; // Slow EMA
input int TrendEMA = 200; // Macro Trend 200 EMA
input int ADX_Period = 14; // ADX Period
input double ADX_Threshold = 20.0; // ADX Chop Filter Minimum
input bool UseTimeFilter = true;
input int StartHour = 9;
input int StartMinute = 30;
input int EndHour = 15;
input int EndMinute = 30;
input ulong MagicNumber = 55555; // Unique EA ID
//--- Globals
CTrade trade;
datetime lastBarTime;
int hFast, hSlow, hTrend, hADX, hATR;
double bufFast[], bufSlow[], bufTrend[], bufADX[], bufATR[];
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
trade.SetExpertMagicNumber(MagicNumber);
hFast = iMA(_Symbol, PERIOD_CURRENT, FastEMA, 0, MODE_EMA, PRICE_CLOSE);
hSlow = iMA(_Symbol, PERIOD_CURRENT, SlowEMA, 0, MODE_EMA, PRICE_CLOSE);
hTrend = iMA(_Symbol, PERIOD_CURRENT, TrendEMA, 0, MODE_EMA, PRICE_CLOSE);
hADX = iADX(_Symbol, PERIOD_CURRENT, ADX_Period);
hATR = iATR(_Symbol, PERIOD_CURRENT, ATR_Period);
ArraySetAsSeries(bufFast, true);
ArraySetAsSeries(bufSlow, true);
ArraySetAsSeries(bufTrend, true);
ArraySetAsSeries(bufADX, true);
ArraySetAsSeries(bufATR, true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
ManageBreakeven();
datetime currentTime = iTime(_Symbol, PERIOD_CURRENT, 0);
if(currentTime == lastBarTime) return; // Wait for bar close
if(UseTimeFilter && !IsTradingTime()) return;
if(PositionsTotal() > 0) return; // Prevent multiple entries
// Update indicator buffers (index 1 is previous closed bar, index 2 is the one before)
if(CopyBuffer(hFast, 0, 1, 2, bufFast) <= 0) return;
if(CopyBuffer(hSlow, 0, 1, 2, bufSlow) <= 0) return;
if(CopyBuffer(hTrend, 0, 1, 1, bufTrend) <= 0) return;
if(CopyBuffer(hADX, 0, 1, 1, bufADX) <= 0) return;
if(CopyBuffer(hATR, 0, 1, 1, bufATR) <= 0) return;
bool buySignal = (bufFast[0] > bufSlow[0] && bufFast[1] <= bufSlow[1]) &&
(iClose(_Symbol, PERIOD_CURRENT, 1) > bufTrend[0]) &&
(bufADX[0] > ADX_Threshold);
bool sellSignal = (bufFast[0] < bufSlow[0] && bufFast[1] >= bufSlow[1]) &&
(iClose(_Symbol, PERIOD_CURRENT, 1) < bufTrend[0]) &&
(bufADX[0] > ADX_Threshold);
if(buySignal) ExecuteTrade(ORDER_TYPE_BUY, bufATR[0]);
if(sellSignal) ExecuteTrade(ORDER_TYPE_SELL, bufATR[0]);
lastBarTime = currentTime;
}
//+------------------------------------------------------------------+
//| Execute Split Trades |
//+------------------------------------------------------------------+
void ExecuteTrade(ENUM_ORDER_TYPE type, double atr)
{
double entryPrice = (type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
double slDist = atr * SL_Multiplier;
double tp1Dist = atr * TP1_Multiplier;
double tp2Dist = atr * TP2_Multiplier;
double sl = (type == ORDER_TYPE_BUY) ? entryPrice - slDist : entryPrice + slDist;
double tp1 = (type == ORDER_TYPE_BUY) ? entryPrice + tp1Dist : entryPrice - tp1Dist;
double tp2 = (type == ORDER_TYPE_BUY) ? entryPrice + tp2Dist : entryPrice - tp2Dist;
sl = NormalizeDouble(sl, _Digits);
tp1 = NormalizeDouble(tp1, _Digits);
tp2 = NormalizeDouble(tp2, _Digits);
double totalLots = CalculateLots(slDist);
double halfLots = NormalizeDouble(totalLots / 2.0, 2);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
if(halfLots < minLot) halfLots = minLot;
// Execute Position 1 (TP1)
trade.PositionOpen(_Symbol, type, halfLots, entryPrice, sl, tp1, "ProScalp TP1");
// Execute Position 2 (TP2)
trade.PositionOpen(_Symbol, type, halfLots, entryPrice, sl, tp2, "ProScalp TP2");
}
//+------------------------------------------------------------------+
//| Manage Breakeven (Trailing Logic) |
//+------------------------------------------------------------------+
void ManageBreakeven()
{
if(CopyBuffer(hATR, 0, 1, 1, bufATR) <= 0) return;
double tp1Dist = bufATR[0] * TP1_Multiplier;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
long type = PositionGetInteger(POSITION_TYPE);
if(type == POSITION_TYPE_BUY)
{
double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(currentBid >= openPrice + tp1Dist && currentSL < openPrice)
trade.PositionModify(ticket, openPrice, PositionGetDouble(POSITION_TP));
}
else if(type == POSITION_TYPE_SELL)
{
double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(currentAsk <= openPrice - tp1Dist && (currentSL > openPrice || currentSL == 0))
trade.PositionModify(ticket, openPrice, PositionGetDouble(POSITION_TP));
}
}
}
}
//+------------------------------------------------------------------+
//| Utilities |
//+------------------------------------------------------------------+
bool IsTradingTime()
{
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
int currentMins = dt.hour * 60 + dt.min;
int startMins = StartHour * 60 + StartMinute;
int endMins = EndHour * 60 + EndMinute;
return (currentMins >= startMins && currentMins <= endMins);
}
double CalculateLots(double slDistance)
{
double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * (RiskPercent / 100.0);
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double slTicks = slDistance / tickSize;
if(slTicks <= 0 || tickValue <= 0) return SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double lots = riskAmount / (slTicks * tickValue);
return NormalizeDouble(lots, 2);
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
Installation & Deployment
1.) Open your MetaTrader platform and press F4 to open the MetaEditor.
2.) In the Navigator on the left, right-click Experts > New File.
3.) Name it Pro_5Min_Scalper, delete everything in the default template, and paste the corresponding code above.
4.) Click Compile (F7). Check the logs at the bottom to ensure there are 0 errors.
5.) Attach it to a 5-Minute Chart. Ensure "Allow Live Trading" / "Allow Algo Trading" is checked in the EA properties.
Note: MT4/MT5 brokers run on their own server time (usually EET). You must adjust the StartHour and EndHour inputs to match your broker's time, not your local computer time.
1.) Open your MetaTrader platform and press F4 to open the MetaEditor.
2.) In the Navigator on the left, right-click Experts > New File.
3.) Name it Pro_5Min_Scalper, delete everything in the default template, and paste the corresponding code above.
4.) Click Compile (F7). Check the logs at the bottom to ensure there are 0 errors.
5.) Attach it to a 5-Minute Chart. Ensure "Allow Live Trading" / "Allow Algo Trading" is checked in the EA properties.
Note: MT4/MT5 brokers run on their own server time (usually EET). You must adjust the StartHour and EndHour inputs to match your broker's time, not your local computer time.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
ranslating this strategy to cTrader (using C# / cAlgo.API) is a fantastic upgrade. cTrader's native architecture handles partial execution, pip math, and position sizing much more elegantly than MetaTrader.
Because cTrader uses Labels instead of Magic Numbers, and processes Stop Loss and Take Profit in Pips rather than absolute price during order execution, the code becomes highly readable. We will maintain the Split-Position architecture (opening two trades with half-volume each) as it ensures the broker server hard-stops both your TP1 and TP2 targets even if your computer disconnects.
The cTrader cBot (C#)
Here is the complete, ready-to-compile cBot code for cTrader.
Because cTrader uses Labels instead of Magic Numbers, and processes Stop Loss and Take Profit in Pips rather than absolute price during order execution, the code becomes highly readable. We will maintain the Split-Position architecture (opening two trades with half-volume each) as it ensures the broker server hard-stops both your TP1 and TP2 targets even if your computer disconnects.
The cTrader cBot (C#)
Here is the complete, ready-to-compile cBot code for cTrader.
Code: Select all
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class Pro5MinScalper : Robot
{
// =========================================================================
// 1. INPUTS: Pro Trade Desk Settings
// =========================================================================
[Parameter("Risk Per Trade (%)", DefaultValue = 1.0, Group = "1. Risk Management")]
public double RiskPercent { get; set; }
[Parameter("ATR Period", DefaultValue = 14, Group = "1. Risk Management")]
public int AtrPeriod { get; set; }
[Parameter("Stop Loss (ATR Multiplier)", DefaultValue = 1.5, Group = "1. Risk Management")]
public double SlMultiplier { get; set; }
[Parameter("TP1 Scale Out (ATR Multiplier)", DefaultValue = 1.5, Group = "1. Risk Management")]
public double Tp1Multiplier { get; set; }
[Parameter("TP2 Runner (ATR Multiplier)", DefaultValue = 3.0, Group = "1. Risk Management")]
public double Tp2Multiplier { get; set; }
[Parameter("Fast EMA", DefaultValue = 9, Group = "2. Trend Filters")]
public int FastEmaPeriod { get; set; }
[Parameter("Slow EMA", DefaultValue = 21, Group = "2. Trend Filters")]
public int SlowEmaPeriod { get; set; }
[Parameter("Macro Trend (200 EMA)", DefaultValue = 200, Group = "2. Trend Filters")]
public int TrendEmaPeriod { get; set; }
[Parameter("ADX Period", DefaultValue = 14, Group = "2. Trend Filters")]
public int AdxPeriod { get; set; }
[Parameter("ADX Minimum (Chop Filter)", DefaultValue = 20.0, Group = "2. Trend Filters")]
public double AdxThreshold { get; set; }
[Parameter("Enable Time Filter", DefaultValue = true, Group = "3. Session Times")]
public bool UseTimeFilter { get; set; }
[Parameter("Start Hour (Server Time)", DefaultValue = 9, Group = "3. Session Times")]
public int StartHour { get; set; }
[Parameter("End Hour (Server Time)", DefaultValue = 15, Group = "3. Session Times")]
public int EndHour { get; set; }
private ExponentialMovingAverage _fastEma;
private ExponentialMovingAverage _slowEma;
private ExponentialMovingAverage _trendEma;
private DirectionalMovementSystem _adx;
private AverageTrueRange _atr;
private const string BotLabel = "ProScalper_5Min";
// =========================================================================
// 2. INITIALIZATION
// =========================================================================
protected override void OnStart()
{
// Initialize indicators using standard cAlgo library
_fastEma = Indicators.ExponentialMovingAverage(Bars.ClosePrices, FastEmaPeriod);
_slowEma = Indicators.ExponentialMovingAverage(Bars.ClosePrices, SlowEmaPeriod);
_trendEma = Indicators.ExponentialMovingAverage(Bars.ClosePrices, TrendEmaPeriod);
_adx = Indicators.DirectionalMovementSystem(AdxPeriod);
_atr = Indicators.AverageTrueRange(AtrPeriod, MovingAverageType.Simple);
}
// =========================================================================
// 3. BREAKEVEN MANAGEMENT (Runs every tick)
// =========================================================================
protected override void OnTick()
{
var openPositions = Positions.FindAll(BotLabel, SymbolName);
if (openPositions.Length == 0) return;
double currentAtr = _atr.Result.Last(1);
double tp1Distance = currentAtr * Tp1Multiplier;
foreach (var pos in openPositions)
{
if (pos.TradeType == TradeType.Buy)
{
// If price reached TP1 equivalent, and SL is still below Entry
if (Symbol.Bid >= pos.EntryPrice + tp1Distance && pos.StopLoss < pos.EntryPrice)
{
ModifyPosition(pos, pos.EntryPrice, pos.TakeProfit);
Print("Long position SL moved to Breakeven.");
}
}
else if (pos.TradeType == TradeType.Sell)
{
// If price reached TP1 equivalent, and SL is still above Entry
if (Symbol.Ask <= pos.EntryPrice - tp1Distance && (pos.StopLoss > pos.EntryPrice || pos.StopLoss == null))
{
ModifyPosition(pos, pos.EntryPrice, pos.TakeProfit);
Print("Short position SL moved to Breakeven.");
}
}
}
}
// =========================================================================
// 4. ENTRY LOGIC (Runs on bar close)
// =========================================================================
protected override void OnBar()
{
// Only take trades if no positions are currently open
if (Positions.FindAll(BotLabel, SymbolName).Length > 0) return;
if (UseTimeFilter && !IsTradingTime()) return;
// Indicator values for the last closed bar (index 1) and the previous (index 2)
int closedBar = Bars.Count - 2;
int prevBar = Bars.Count - 3;
bool buySignal = _fastEma.Result[closedBar] > _slowEma.Result[closedBar] &&
_fastEma.Result[prevBar] <= _slowEma.Result[prevBar] &&
Bars.ClosePrices[closedBar] > _trendEma.Result[closedBar] &&
_adx.ADX[closedBar] > AdxThreshold;
bool sellSignal = _fastEma.Result[closedBar] < _slowEma.Result[closedBar] &&
_fastEma.Result[prevBar] >= _slowEma.Result[prevBar] &&
Bars.ClosePrices[closedBar] < _trendEma.Result[closedBar] &&
_adx.ADX[closedBar] > AdxThreshold;
if (buySignal) ExecuteSplitTrade(TradeType.Buy);
if (sellSignal) ExecuteSplitTrade(TradeType.Sell);
}
// =========================================================================
// 5. TRADE EXECUTION & MATH
// =========================================================================
private void ExecuteSplitTrade(TradeType direction)
{
double atr = _atr.Result.Last(1);
// Calculate distances in absolute price, then convert to Pips for cTrader API
double slDistPrice = atr * SlMultiplier;
double tp1DistPrice = atr * Tp1Multiplier;
double tp2DistPrice = atr * Tp2Multiplier;
double slPips = slDistPrice / Symbol.PipSize;
double tp1Pips = tp1DistPrice / Symbol.PipSize;
double tp2Pips = tp2DistPrice / Symbol.PipSize;
// Position Sizing based on Risk %
double totalVolume = CalculateVolume(slPips);
double halfVolume = Symbol.NormalizeVolumeInUnits(totalVolume / 2.0, RoundingMode.Down);
// Enforce broker minimums
if (halfVolume < Symbol.VolumeInUnitsMin)
halfVolume = Symbol.VolumeInUnitsMin;
// Execute Position 1 (Take Profit 1)
ExecuteMarketOrder(direction, SymbolName, halfVolume, BotLabel, slPips, tp1Pips);
// Execute Position 2 (Take Profit 2 - The Runner)
ExecuteMarketOrder(direction, SymbolName, halfVolume, BotLabel, slPips, tp2Pips);
}
private double CalculateVolume(double stopLossPips)
{
double riskAmount = Account.Equity * (RiskPercent / 100.0);
// Symbol.PipValue is the value of 1 pip for 1 unit of volume in cTrader
double exactVolume = riskAmount / (stopLossPips * Symbol.PipValue);
return exactVolume;
}
private bool IsTradingTime()
{
DateTime time = Server.Time;
int currentMins = time.Hour * 60 + time.Minute;
int startMins = StartHour * 60 + StartMinute;
int endMins = EndHour * 60 + EndMinute;
return (currentMins >= startMins && currentMins <= endMins);
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The 5-Minute Chart: The Scalper's Middle Ground
How to Install it in cTrader:
1.) Open cTrader and click on the Automate tab on the left sidebar (the robot icon).
2.) Click New cBot at the top right of the bots list. Name it Pro_5Min_Scalper.
3.) The code editor will open. Delete everything inside, and paste the code provided above.
4.) Click the Build button (the hammer icon or Ctrl+B) at the top of the editor. Ensure you see "Build Succeeded" in the output window.
5.) Go to your 5-Minute chart, click the cBots dropdown at the top of the chart, and add Pro_5Min_Scalper to the chart.
1.) Open cTrader and click on the Automate tab on the left sidebar (the robot icon).
2.) Click New cBot at the top right of the bots list. Name it Pro_5Min_Scalper.
3.) The code editor will open. Delete everything inside, and paste the code provided above.
4.) Click the Build button (the hammer icon or Ctrl+B) at the top of the editor. Ensure you see "Build Succeeded" in the output window.
5.) Go to your 5-Minute chart, click the cBots dropdown at the top of the chart, and add Pro_5Min_Scalper to the chart.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.