// ========================================================================
// STRATEGY: DMI-ADX Crossover with Stop Loss + Opposite Signal Exit
// ========================================================================
// BT-DMI-test-V3.0.13.2-VS-AQ
// === INPUTS ===
myDMIperiod = myDMIperiod // 10 // optimize from 1 to 20 via PRT Platform
myATRperiod = 14
myATRmultiplier = 2.5
myRiskPercent = 5 // Risk percentage (5%)
myInitialBalance = 100000 // Starting capital
myADXThreshold = 20 // Minimum ADX value for trend strength confirmation
// === INDICATORS ===
myDIplus = DIPLUS[myDMIperiod]
myDIminus = DIMINUS[myDMIperiod]
myADX = ADX[myDMIperiod]
myATR = AVERAGETRUERANGE[myATRperiod]
// === SIGNALS ===
// Basic DMI crossover signals - SAME BAR ENTRY
myLongSignal = myDIplus CROSSES OVER myDIminus
myShortSignal = myDIminus CROSSES OVER myDIplus
// ADX trend strength filter
// ADXStrong: Filter out weak trends to avoid whipsaw trades in choppy markets
myADXStrong = myADX > myADXThreshold
// Final signals with filter applied
myLongSignal = myLongSignal AND myADXStrong
myShortSignal = myShortSignal AND myADXStrong
// === STOP LOSS DISTANCE ===
myStopLossDistance = myATR * myATRmultiplier
// === RISK MANAGEMENT ===
// Initialize account balance tracking
ONCE myCurrentBalance = myInitialBalance
ONCE myPreviousEquity = myInitialBalance
ONCE myProfitLoss = 0
// Update account balance based on closed positions
IF BarsSince(LongOnMarket) = 0 OR BarsSince(ShortOnMarket) = 0 THEN
// New position opened
myPreviousEquity = myCurrentBalance
ENDIF
// If position was closed on previous bar, update the balance
IF (LongOnMarket[1] AND NOT LongOnMarket) OR (ShortOnMarket[1] AND NOT ShortOnMarket) THEN
// Calculate profit/loss from the closed position
IF LongOnMarket[1] THEN
myProfitLoss = (close[1] - POSITIONPRICE[1]) * COUNTOFPOSITION[1]
ELSE
myProfitLoss = (POSITIONPRICE[1] - close[1]) * ABS(COUNTOFPOSITION[1])
ENDIF
// Update current balance
myCurrentBalance = myCurrentBalance + myProfitLoss
ENDIF
// Calculate position size based on risk
myRiskAmount = myCurrentBalance * (myRiskPercent / 100)
// Calculate position size based on stop loss distance
IF myStopLossDistance > 0 THEN
myRiskBasedPositionSize = ROUND(myRiskAmount / myStopLossDistance)
// Ensure minimum position size of 1
IF myRiskBasedPositionSize < 1 THEN
myRiskBasedPositionSize = 1
ENDIF
ELSE
myRiskBasedPositionSize = 1
ENDIF
// === STATE FLAGS ===
// Initialize these variables only once to maintain state between bars
ONCE myReverseToLong = 0
ONCE myReverseToShort = 0
ONCE myEntryPrice = 0
ONCE myLongStopLevel = 0
ONCE myShortStopLevel = 0
ONCE myExitType = 0 // 0=neutral, +1=opposite signal, -1=stop loss hit
ONCE myExitPrice = 0 // Price at which exit occurred
// === POSITION MANAGEMENT ===
IF LongOnMarket THEN
// Store entry price when entering a position
IF BarsSince(LongOnMarket) = 0 THEN
myEntryPrice = close
myLongStopLevel = myEntryPrice - myStopLossDistance
myExitType = 0
myExitPrice = 0
// Set stop loss using built-in function
SET STOP PRICE myLongStopLevel
ENDIF
ENDIF
IF ShortOnMarket THEN
// Store entry price when entering a position
IF BarsSince(ShortOnMarket) = 0 THEN
myEntryPrice = close
myShortStopLevel = myEntryPrice + myStopLossDistance
myExitType = 0
myExitPrice = 0
// Set stop loss using built-in function
SET STOP PRICE myShortStopLevel
ENDIF
ENDIF
// === ENTRY WHEN FLAT ===
IF NOT LongOnMarket AND NOT ShortOnMarket THEN
IF myReverseToLong THEN
BUY myRiskBasedPositionSize SHARES AT MARKET
myReverseToLong = 0
ELSE
IF myReverseToShort THEN
SELLSHORT myRiskBasedPositionSize SHARES AT MARKET
myReverseToShort = 0
ELSE
IF myLongSignal THEN
BUY myRiskBasedPositionSize SHARES AT MARKET
ELSE
IF myShortSignal THEN
SELLSHORT myRiskBasedPositionSize SHARES AT MARKET
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
// === VISUALIZATION ===
// Show stop levels on price chart
GraphOnPrice myLongStopLevel coloured("Green")
GraphOnPrice myShortStopLevel coloured("Red")
// Track exit types in a separate panel
GRAPH myExitType AS "Exit Type (+1=Signal, 0=Neutral, -1=Stop Loss)"
// End
Hiya all coders,
This one has had my head pickled of late!!!
PLEASE NOTE: I only ever use the daily: 1 day / 1 bar.
Background:
—————
To get a backtest benchmark, I use a fixed stop loss.
Once the fixed stop loss backtest has been validated,
I then move to a training stop system.
I have found a way to validate the exit type (Separate panel)
1. Stop loss hit SL (-1)
2. Opposite signal triggered OS (+1)
This is working and a good visual for said exit types.
And provides a useful visual of the trade entry system, and its exit.
Issue:
——–
Currently, my code is not detecting the stop loss hits, and thus the trade continues!
When the SL is detected, it can be days / bars later.
I also notice that there are occurrences where the trade exit is nowhere near a stop loss level or an opposite signal !
I have used both the system code => SET STOP PRICE
And a manual check, ‘high or low’ values of the latest bar.
The opposite signal trigger is working – and for some reason, the OS check is occurring before the SL!!!
Subjectively:
—————-
The stop loss SL check should be performed before the opposite signal OS check.
If, during the day, the price has been higher or lower than the SL level, then the SL should be triggered before the next bar / next day.
if no stop loss is triggered, then the OS check should be performed, and if triggered the open trade is closed, and the opposite trade is opened (on the same bar)
I hope this explanation makes sense.
I appreciate any code guidance that provides a working solution.
My thanks always.
NT