Page 1 of 1

Stop Looking for the Perfect Strategy

Posted: Mon Sep 21, 2026 8:56 pm
by dreambig
I think one of the biggest traps in trading is constantly looking for a better strategy.

You find a strategy.

You backtest it.
It works reasonably well.
You start trading it.

Then you have a losing streak.

Suddenly you start thinking:

“Maybe this strategy doesn’t work anymore.”

So you go on YouTube, Reddit or TradingView looking for something better.

You find another strategy.

It looks even better.

So you switch.

And then the same thing happens again.

I have done this more times than I would like to admit.

The problem is that there will probably never be a strategy that wins all the time.

Even a strategy with a 50% win rate can easily give you 4, 5 or even more losses in a row. That doesn’t automatically mean the strategy is broken.

At some point I realized that I wasn’t really looking for a better strategy.

I was looking for a strategy that would make losing trades less painful.

And that strategy doesn’t exist.

Every profitable strategy will have losing trades. There will be bad days. There will be periods when nothing seems to work.

The important question isn’t:

“Is there a better strategy?”

It’s:

“Can I execute this strategy consistently enough to find out whether it actually works?”

Because constantly changing strategies means you never really give any of them a fair chance.

You change the rules after a losing streak, then change them again after another few losses.

Eventually you don’t even know whether your strategy is profitable or whether you are the problem.

I think traders should spend less time searching for the perfect entry and more time learning how to execute one decent strategy consistently.

The perfect strategy probably doesn’t exist.

But a simple strategy that you understand, have tested and can follow without constantly changing the rules?

DreamBig

Re: Stop Looking for the Perfect Strategy

Posted: Tue Sep 22, 2026 1:55 pm
by PTScalper
dreambig wrote: Mon Sep 21, 2026 8:56 pm I think one of the biggest traps in trading is constantly looking for a better strategy.

You find a strategy.

You backtest it.
It works reasonably well.
You start trading it.

Then you have a losing streak.

Suddenly you start thinking:

“Maybe this strategy doesn’t work anymore.”

So you go on YouTube, Reddit or TradingView looking for something better.

You find another strategy.

It looks even better.

So you switch.

And then the same thing happens again.

I have done this more times than I would like to admit.

The problem is that there will probably never be a strategy that wins all the time.

Even a strategy with a 50% win rate can easily give you 4, 5 or even more losses in a row. That doesn’t automatically mean the strategy is broken.

At some point I realized that I wasn’t really looking for a better strategy.

I was looking for a strategy that would make losing trades less painful.

And that strategy doesn’t exist.

Every profitable strategy will have losing trades. There will be bad days. There will be periods when nothing seems to work.

The important question isn’t:

“Is there a better strategy?”

It’s:

“Can I execute this strategy consistently enough to find out whether it actually works?”

Because constantly changing strategies means you never really give any of them a fair chance.

You change the rules after a losing streak, then change them again after another few losses.

Eventually you don’t even know whether your strategy is profitable or whether you are the problem.

I think traders should spend less time searching for the perfect entry and more time learning how to execute one decent strategy consistently.

The perfect strategy probably doesn’t exist.

But a simple strategy that you understand, have tested and can follow without constantly changing the rules?

DreamBig
Hi DreamBig,

Strategy hopping is the silent account killer, and realizing that you are looking for a psychological safety net rather than a statistical edge is a massive milestone in a trader's journey.

The hard truth is that the "ideal" forex strategy simply does not exist. The market is fractal, dynamic, and constantly shifting between volatility cycles. A strategy designed to crush it in a trending market will inevitably experience drawdowns during a choppy, ranging market.

The goal isn't to find a holy grail that never loses. The goal is to find a robust strategy that can survive the long term across all kinds of market conditions—and most importantly, a strategy that suits your personality.

If you don't have the patience to sit through days of no setups, a daily-chart swing trading system will drive you crazy and force you into bad trades. Conversely, if you can't handle split-second pressure, 15-minute raw price action scalping will eat you alive. Your strategy must match your screen time, risk tolerance, and psychological makeup. Once you find that fit, you stop changing the rules and start focusing purely on execution.

Re: Stop Looking for the Perfect Strategy

Posted: Tue Sep 22, 2026 1:56 pm
by PTScalper
To help you (and anyone else reading) actually stick to testing a single concept rather than blindly jumping to the next YouTube trend, here is a clean, modular Pine Script v5 backtesting template. You can plug your own raw price action logic into it, test it over years of data, and actually see those losing streaks in the backtester so you don't panic when they happen live.

Code: Select all

//@version=5
strategy("Robust Backtest Template", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=1, commission_type=strategy.commission.cash_per_order, commission_value=3)

// =========================================================================
// 1. TIME FILTER 
// (Crucial to see how the strategy performs across different market cycles)
// =========================================================================
useDateFilter = input.bool(true, title="Filter Date Range of Backtest", group="Time Settings")
backtestStartDate = input.time(timestamp("2023-01-01T00:00:00"), title="Start Date", group="Time Settings")
backtestEndDate = input.time(timestamp("2026-12-31T00:00:00"), title="End Date", group="Time Settings")

inTradeWindow = not useDateFilter or (time >= backtestStartDate and time <= backtestEndDate)

// =========================================================================
// 2. STRATEGY LOGIC (Replace this with your own rules)
// =========================================================================
// Example: Basic Price Action - Engulfing Candles as a placeholder
bullishEngulfing = close[1] < open[1] and close > open and close > open[1] and open < close[1]
bearishEngulfing = close[1] > open[1] and close < open and close < open[1] and open > close[1]

longCondition  = bullishEngulfing
shortCondition = bearishEngulfing

// =========================================================================
// 3. RISK MANAGEMENT & EXECUTION
// =========================================================================
slPoints = input.int(150, title="Stop Loss (Points)", group="Risk Management")
tpPoints = input.int(300, title="Take Profit (Points)", group="Risk Management")

if (inTradeWindow and longCondition and strategy.position_size == 0)
    strategy.entry("Long", strategy.long)
    strategy.exit("Exit Long", "Long", loss=slPoints, profit=tpPoints)

if (inTradeWindow and shortCondition and strategy.position_size == 0)
    strategy.entry("Short", strategy.short)
    strategy.exit("Exit Short", "Short", loss=slPoints, profit=tpPoints)

// =========================================================================
// 4. VISUALIZATION
// =========================================================================
plotshape(series=longCondition and strategy.position_size == 0, title="Long Signal", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
plotshape(series=shortCondition and strategy.position_size == 0, title="Short Signal", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)

Re: Stop Looking for the Perfect Strategy

Posted: Tue Sep 22, 2026 1:56 pm
by PTScalper
By using a framework like this, you can code your exact entry and exit rules, run it through years of data, and look specifically at the Max Drawdown and Consecutive Losses tabs. When you know mathematically that your strategy is expected to lose 6 times in a row at some point, that 4th consecutive loss in the live market suddenly feels like part of the plan instead of a reason to abandon ship.

Re: Stop Looking for the Perfect Strategy

Posted: Tue Sep 22, 2026 1:57 pm
by PTScalper
Here are the direct translations of the backtesting framework into both MQL4 and MQL5. They maintain the same modular structure: an overarching time filter, a dedicated block for raw price action logic, and strict risk management rules to keep backtests realistic.

You can drag either of these EAs directly onto a 15-minute or daily chart in the Strategy Tester and immediately start seeing how the candlestick logic handles different market conditions over time.

MetaTrader 4 (MQL4)

Code: Select all

//+------------------------------------------------------------------+
//|                                             Robust_Template_MT4.mq4|
//+------------------------------------------------------------------+
#property strict

// =========================================================================
// 1. TIME FILTER
// =========================================================================
input bool   UseDateFilter = true;        
input string StartDate = "2023.01.01 00:00"; 
input string EndDate   = "2026.12.31 00:00"; 

// =========================================================================
// 2. RISK MANAGEMENT
// =========================================================================
input double LotSize = 0.1;               
input int    SLPoints = 150;              
input int    TPPoints = 300;              
input int    MagicNumber = 123456;        

datetime start_time, end_time;
double pnt;

//+------------------------------------------------------------------+
int OnInit() {
    start_time = StringToTime(StartDate);
    end_time   = StringToTime(EndDate);
    pnt        = Point;
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnTick() {
    if(UseDateFilter && (TimeCurrent() < start_time || TimeCurrent() > end_time)) return;
    
    // Ensure we trigger on a new bar only to prevent log spam and intra-bar repainting
    static datetime lastBarTime;
    datetime currentBarTime = iTime(Symbol(), PERIOD_CURRENT, 0);
    if(currentBarTime == lastBarTime) return;
    lastBarTime = currentBarTime;

    // Check for open positions
    bool hasPosition = false;
    for(int i = OrdersTotal() - 1; i >= 0; i--) {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) {
                hasPosition = true;
                break;
            }
        }
    }
    if(hasPosition) return;

    // =========================================================================
    // 3. STRATEGY LOGIC (Placeholder: Engulfing Candles)
    // =========================================================================
    double O1 = iOpen(Symbol(), 0, 1);
    double C1 = iClose(Symbol(), 0, 1);
    double O2 = iOpen(Symbol(), 0, 2);
    double C2 = iClose(Symbol(), 0, 2);

    bool bullishEngulfing = (C2 < O2) && (C1 > O1) && (C1 > O2) && (O1 < C2);
    bool bearishEngulfing = (C2 > O2) && (C1 < O1) && (C1 < O2) && (O1 > C2);
    
    // =========================================================================
    // 4. EXECUTION
    // =========================================================================
    if(bullishEngulfing) {
        double sl = NormalizeDouble(Ask - (SLPoints * pnt), Digits);
        double tp = NormalizeDouble(Ask + (TPPoints * pnt), Digits);
        OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp, "Long Entry", MagicNumber, 0, clrGreen);
    }
    
    if(bearishEngulfing) {
        double sl = NormalizeDouble(Bid + (SLPoints * pnt), Digits);
        double tp = NormalizeDouble(Bid - (TPPoints * pnt), Digits);
        OrderSend(Symbol(), OP_SELL, LotSize, Bid, 3, sl, tp, "Short Entry", MagicNumber, 0, clrRed);
    }
}

Re: Stop Looking for the Perfect Strategy

Posted: Tue Sep 22, 2026 1:58 pm
by PTScalper
MetaTrader 5 (MQL5)

MT5 uses the CTrade standard library class, which dramatically simplifies order execution compared to raw OrderSend calls.

Code: Select all

//+------------------------------------------------------------------+
//|                                             Robust_Template_MT5.mq5|
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>

CTrade trade;

// =========================================================================
// 1. TIME FILTER
// =========================================================================
input bool     UseDateFilter = true;                  
input datetime StartDate = D'2023.01.01 00:00';       
input datetime EndDate   = D'2026.12.31 00:00';       

// =========================================================================
// 2. RISK MANAGEMENT
// =========================================================================
input double LotSize = 0.1;           
input int    SLPoints = 150;          
input int    TPPoints = 300;          
input ulong  MagicNumber = 123456;    

double pnt;

//+------------------------------------------------------------------+
int OnInit() {
    trade.SetExpertMagicNumber(MagicNumber);
    pnt = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnTick() {
    datetime currentTime = TimeCurrent();
    if(UseDateFilter && (currentTime < StartDate || currentTime > EndDate)) return;

    // Ensure we trigger on a new bar only
    static datetime lastBarTime;
    datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
    if(currentBarTime == lastBarTime) return;
    lastBarTime = currentBarTime;

    // Check for open positions
    bool hasPosition = false;
    for(int i = PositionsTotal() - 1; i >= 0; i--) {
        ulong ticket = PositionGetTicket(i);
        if(ticket > 0) {
            if(PositionGetString(POSITION_SYMBOL) == _Symbol) {
                if(PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
                    hasPosition = true;
                    break;
                }
            }
        }
    }
    if(hasPosition) return;

    // =========================================================================
    // 3. STRATEGY LOGIC (Placeholder: Engulfing Candles)
    // =========================================================================
    double O[3], C[3];
    if(CopyOpen(_Symbol, PERIOD_CURRENT, 0, 3, O) != 3) return;
    if(CopyClose(_Symbol, PERIOD_CURRENT, 0, 3, C) != 3) return;
    
    // Arrays in MQL5 CopyOpen/Close are ordered from oldest (0) to newest (2)
    double O2 = O[0]; // Two bars ago
    double C2 = C[0];
    double O1 = O[1]; // Previous completed bar
    double C1 = C[1];

    bool bullishEngulfing = (C2 < O2) && (C1 > O1) && (C1 > O2) && (O1 < C2);
    bool bearishEngulfing = (C2 > O2) && (C1 < O1) && (C1 < O2) && (O1 > C2);

    // =========================================================================
    // 4. EXECUTION
    // =========================================================================
    double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

    if(bullishEngulfing) {
        double sl = NormalizeDouble(ask - (SLPoints * pnt), _Digits);
        double tp = NormalizeDouble(ask + (TPPoints * pnt), _Digits);
        trade.Buy(LotSize, _Symbol, ask, sl, tp, "Long Entry");
    }
    
    if(bearishEngulfing) {
        double sl = NormalizeDouble(bid + (SLPoints * pnt), _Digits);
        double tp = NormalizeDouble(bid - (TPPoints * pnt), _Digits);
        trade.Sell(LotSize, _Symbol, bid, sl, tp, "Short Entry");
    }
}

Re: Stop Looking for the Perfect Strategy

Posted: Tue Sep 22, 2026 2:00 pm
by PTScalper
Since cTrader uses C# (.NET) for its cAlgo API, we can build a much cleaner event-driven structure than MetaTrader. Instead of tracking timestamps inside an OnTick loop to detect new candles, we can natively use the OnBar method to execute logic only when a candle closes.

This template keeps the exact same modular structure (Time Filter, Strategy Logic, Execution) and exposes the settings directly to the cTrader parameter grid for optimization.

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 RobustTemplate_cTrader : Robot
    {
        // =========================================================================
        // 1. TIME FILTER
        // =========================================================================
        [Parameter("Use Date Filter", Group = "Time Settings", DefaultValue = true)]
        public bool UseDateFilter { get; set; }

        [Parameter("Start Date", Group = "Time Settings", DefaultValue = "2023-01-01 00:00:00")]
        public string StartDateString { get; set; }

        [Parameter("End Date", Group = "Time Settings", DefaultValue = "2026-12-31 00:00:00")]
        public string EndDateString { get; set; }

        // =========================================================================
        // 2. RISK MANAGEMENT
        // =========================================================================
        [Parameter("Volume (Lots)", Group = "Risk Management", DefaultValue = 0.1)]
        public double VolumeInLots { get; set; }

        [Parameter("Stop Loss (Pips)", Group = "Risk Management", DefaultValue = 15.0)]
        public double SlPips { get; set; }

        [Parameter("Take Profit (Pips)", Group = "Risk Management", DefaultValue = 30.0)]
        public double TpPips { get; set; }

        private DateTime _startDate;
        private DateTime _endDate;
        private const string MyLabel = "RobustTemplate";

        protected override void OnStart()
        {
            // Parse date strings to DateTime objects during initialization
            if (!DateTime.TryParse(StartDateString, out _startDate))
                Print("Invalid Start Date format. Use yyyy-MM-dd HH:mm:ss");
            
            if (!DateTime.TryParse(EndDateString, out _endDate))
                Print("Invalid End Date format. Use yyyy-MM-dd HH:mm:ss");
        }

        // OnBar executes exactly once per candle close, removing the need for new-bar tracking
        protected override void OnBar() 
        {
            // Date Filter Check
            if (UseDateFilter && (Server.Time < _startDate || Server.Time > _endDate))
                return;

            // Check for existing open positions belonging to this specific bot
            var openPositions = Positions.Count(p => p.SymbolName == SymbolName && p.Label == MyLabel);
            if (openPositions > 0)
                return;

            // =========================================================================
            // 3. STRATEGY LOGIC (Placeholder: Engulfing Candles)
            // =========================================================================
            // Bars.Last(0) is the currently forming, unclosed bar. 
            // Bars.Last(1) is the previous fully closed bar.
            
            double O1 = Bars.OpenPrices.Last(1);
            double C1 = Bars.ClosePrices.Last(1);
            double O2 = Bars.OpenPrices.Last(2);
            double C2 = Bars.ClosePrices.Last(2);

            bool bullishEngulfing = (C2 < O2) && (C1 > O1) && (C1 > O2) && (O1 < C2);
            bool bearishEngulfing = (C2 > O2) && (C1 < O1) && (C1 < O2) && (O1 > C2);

            // =========================================================================
            // 4. EXECUTION
            // =========================================================================
            // cTrader requires volume in actual units (e.g., 10,000 for 0.1 lots)
            double volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);

            if (bullishEngulfing)
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, volumeInUnits, MyLabel, SlPips, TpPips);
            }
            else if (bearishEngulfing)
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, volumeInUnits, MyLabel, SlPips, TpPips);
            }
        }
    }
}

Re: Stop Looking for the Perfect Strategy

Posted: Wed Sep 23, 2026 7:28 pm
by LondonScalper
PTScalper wrote:By using a framework like this, you can code your exact entry and exit rules, run it through years of data, and look specifically at the Max Drawdown and Consecutive Losses tabs.
Max drawdown and consecutive-loss tabs are the parts of a test I actually read. Perfect strategy shopping is usually a way to avoid sitting with one average plan for a full quarter.

I would rather run a plain rule set through ugly years and know the worst streak than polish entries until the curve looks polite. Live size should respect that streak, not the best month.

After enough years the edge is boring execution plus refusal to reinvent the book every Monday.

When you review a test, which number forces you to cut size before you ever go live?

Re: Stop Looking for the Perfect Strategy

Posted: Thu Sep 24, 2026 12:12 am
by PropScalpDesk
PTScalper wrote:Since cTrader uses C# (.NET) for its cAlgo API, we can build a much cleaner event-driven structure than MetaTrader.
I stopped hunting perfect strategies when drawdown and streak tabs started mattering more than pretty curves. One average plan survived a quarter beats three polished toys that die on week two.

Prop size respects the worst streak in the sample, not the best month on the sales page.

When you review a test, which number forces a size cut before go-live?

I also log refused tickets so flat time counts as work — otherwise the desk invents activity.

Funded trailing DD is the external referee that keeps the desk honest.

Boring survival beats a clever recovery that spends the week’s DD band.

Topic note from my sheet for t=12584: keep risk unchanged until the sample says otherwise.

Re: Stop Looking for the Perfect Strategy

Posted: Thu Sep 24, 2026 7:08 am
by LondonNewsTrader
PTScalper wrote:Since cTrader uses C# (.NET) for its cAlgo API, we can build a much cleaner event-driven structure than MetaTrader.
The modular layout is tidy, and that's also the risk for this particular thread. When the strategy block is a ten-line placeholder you can swap in an afternoon, strategy-hopping gets cheaper, not rarer. If I used this, I'd put a version string into the label (RobustTemplate_v3, say) so every trade in history is tied to the exact logic that produced it. A losing streak then gets judged against its own sample instead of blending three ideas together.

Code-wise, the End Date default of 2026-12-31 means the bot will quietly stop opening trades on the first of January and nothing will tell you. DateTime.TryParse also depends on the machine's culture settings, so on a VPS with a European locale that string may not parse the way you expect; ParseExact with a fixed format is safer.

The fixed 15/30 pip bracket and 0.1 lots ignore volatility entirely. On a quiet Asian drift 15 pips is miles; around a Tier-1 release on GBPUSD it can be one candle. Scaling SL and TP off ATR, and sizing from risk rather than fixed lots, would make the optimisation results mean more.

The engulfing comparison itself reads correctly for closed bars.