Jump to content

Alpha Research: Difference between revisions

From PlusEV Wiki Page
No edit summary
No edit summary
Line 1: Line 1:
__NOTOC__
= Alpha Research: MCX Crude Oil MA21 Strategy =


'''Alpha Research: MCX Crude Oil MA21 Strategy'''
'''Single Source of Truth for the PlusEV Trading System'''
 
''Single Source of Truth for the PlusEV Trading System''


----
----
Line 12: Line 10:
! Metric !! Value !! Notes
! Metric !! Value !! Notes
|-
|-
| Total P&L || Rs +25,48,101 || 19-month validation period
| '''Total P&L''' || Rs +25,48,101 || 19-month validation period
|-
|-
| Win Rate || 57.6% || Above 55% threshold
| '''Win Rate''' || 57.6% || Above 55% threshold
|-
|-
| Profit Factor || 1.20 || Risk-adjusted returns
| '''Profit Factor''' || 1.20 || Risk-adjusted returns
|-
|-
| Total Trades || 7,534 || Statistical significance
| '''Total Trades''' || 7,534 || Statistical significance
|-
|-
| Initial Capital || Rs 1,00,000 || Starting portfolio
| '''Initial Capital''' || Rs 1,00,000 || Starting portfolio
|-
|-
| Final Capital || Rs 26,48,101 || 2548% return
| '''Final Capital''' || Rs 26,48,101 || 2548% return
|}
|}


'''Branch''': <code>rikk_mtf_backtest001</code>
'''Branch''': <code>rikk_mtf_backtest001</code> | '''Commit''': <code>68dae212</code>
'''Commit''': <code>68dae212</code>


''"In trading systems, empirical results > theoretical understanding. If the backtest shows it works, we ship it."''
{{quote|In trading systems, empirical results > theoretical understanding. If the backtest shows it works, we ship it.}}


----
----


== Core Trading Philosophy ==
= Part 1: Core Trading Philosophy =
 
== 1.1 Foundational Principles ==


=== Foundational Principles ===
<pre>
* Simple systems outperform complex ones
Simple systems outperform complex ones.
* Market behavior is probabilistic, not predictive
Market behavior is probabilistic, not predictive.
* Goal is asymmetric probability positioning, not prediction
The goal is positioning with asymmetric probabilities, not prediction.
</pre>


=== Asymmetric Probability Edge ===
=== The Asymmetric Probability Edge ===
When continuation probability drops, reversal odds rise.


* 15% continuation ⇒ ~85% reversal probability
When odds are low on one outcome, '''the opposite side usually carries high odds''':
* Strategy positions on the higher-probability side
* If new high probability drops to 15%, then '''85% odds favor reversal'''
* We position ourselves on the high-probability side


----
----


== Probability Zones (Halves & Thirds) ==
== 1.2 Probability Zones (Halves & Thirds) ==


* Top Third → ~80% continuation (SHORT zone)
Every large move is divided into '''halves and thirds''', creating probability zones.
* Top Half → ~65% continuation
 
* Bottom Half → ~35% continuation
=== Odds of Continuation After Pullback ===
* Bottom Third → ~15% continuation (LONG zone with 85% reversal odds)


<pre>
<pre>
enable_probability_zone_filter = True
┌─────────────────────────────────────────────────────┐
probability_zone_swing_lookback = 20
│  SWING HIGH                                        │
probability_zone_min_range = 20.0
├─────────────────────────────────────────────────────┤
│  TOP THIRD        →  ~80% chance of new high        │  ← IDEAL SHORT ZONE
├─────────────────────────────────────────────────────┤
│  TOP HALF        →  ~65% chance of new high        │
├─────────────────────────────────────────────────────┤
│  BOTTOM HALF      →  ~35% chance of new high        │
├─────────────────────────────────────────────────────┤
│  BOTTOM THIRD    →  ~15% chance of new high        │  ← IDEAL LONG ZONE
├─────────────────────────────────────────────────────┤
│  SWING LOW                                          │
└─────────────────────────────────────────────────────┘
</pre>
</pre>
=== Code Implementation ===
<syntaxhighlight lang="python">
# File: signal_generation_trade_management.py:99-109
enable_probability_zone_filter: bool = True
probability_zone_swing_lookback: int = 20    # Bars to find swing H/L
probability_zone_min_range: float = 20.0    # Min range for valid zone
</syntaxhighlight>


----
----


== Crash Play (Core Strategy) ==
== 1.3 The Crash Play (Core Strategy) ==
 
=== What is a Crash Bar? ===
* '''Much larger''' than recent bars
* '''Fast, violent, elongated''' movement
* Indicates a '''structural break'''


=== Crash Bar Definition ===
=== The Crash Play Logic ===
* Bar > 2x recent average size
* Fast, violent, elongated move
* Indicates structural break


=== Crash Play Logic ===
<pre>
<pre>
1. Identify crash bar
1. Identify crash bar (bar > 2x average size)
2. Divide into halves & thirds
2. Divide it into halves and thirds
3. Watch for bounce into zones
3. Watch for bounce INTO these zones
4. Enter on color change or upper-zone test
4. Enter when:
  - Color change confirms (red overtakes green), OR
  - Price reaches upper zones
</pre>
</pre>


'''Statistical Edge'''
=== Key Statistics ===
* ~85% odds favor continuation after crash
* After a crash, bounces have only '''~15% odds''' of reclaiming highs
* '''~85% odds''' favor continuation lower
* '''Bounces after crashes are statistically SHORT opportunities'''
 
=== Code Implementation ===
<syntaxhighlight lang="python">
# File: signal_generation_trade_management.py:108
crash_bar_multiplier: float = 2.0  # Bar must be 2x average for crash detection
</syntaxhighlight>
 
----
 
== 1.4 Pullback vs Collapse (Critical Distinction) ==
 
=== Healthy Pullback (Tradeable) ===
 
{| class="wikitable"
! Characteristic !! Description
|-
| Angle || 45-degree drifting decline, NOT vertical
|-
| Bars || No violent or oversized red bars
|-
| Depth || Holds '''above halfway point''' of prior run
|-
| Confirmation || Color change (green overtakes red)
|}
 
'''Interpretation''': Pullbacks are rests, not reversals. Odds favor continuation.
 
=== Collapse (NOT Tradeable) ===


{| class="wikitable"
! Characteristic !! Description
|-
| Angle || Vertical, elongated, violent first drop
|-
| Depth || Breaks deeply into or below prior run
|-
| Momentum || Abrupt and forceful
|}
'''Interpretation''': Indicates institutional selling. Bounces are sucker plays.
----
== 1.5 Identifying Market Tops (4 Characteristics) ==
Major tops usually exhibit '''at least 2 of these 4 characteristics''':
=== 1. Three-to-Five Leg Run-Up ===
<pre>
Markets top between leg 3 and leg 5.
- Buy: legs 1-2
- Ride: leg 3
- Take profits: legs 4-5
- Buying late (leg 4-5) = large downside vs small upside
</pre>
=== 2. Vertical Acceleration in Final Leg ===
<pre>
If the last leg is STEEPER than prior legs → likely final leg
The most vertical leg is usually the top.
</pre>
=== 3. Exhaustion Bar ===
<pre>
<pre>
crash_bar_multiplier = 2.0
Final bar of final leg is:
- Larger than recent bars
- Often the largest bar of entire run
= Bulls deploy all remaining buying power
= Market becomes top-heavy and vulnerable
</pre>
</pre>
=== 4. Three-Finger Spread (Dual Space) ===
<pre>
Large separation between:
- Price
- 21-period MA
- 200-period MA
= Many traders holding large unrealized profits
= Any red bar can trigger mass profit-taking
= Creates fast, violent declines
</pre>
=== Code Implementation ===
<syntaxhighlight lang="python">
# File: signal_generation_trade_management.py:107
three_finger_spread_threshold: float = 0.02  # 2% min spread for detection
</syntaxhighlight>


----
----


== Pullback vs Collapse ==
= Part 2: Entry Methodology =
 
== 2.1 The Fab Four Concept ==


=== Healthy Pullback ===
The '''Fab Four''' defines the key reference points for entries and stops:
* 45-degree drift
* No violent bars
* Holds above midpoint
* Odds favor continuation


=== Collapse (No Trade) ===
<pre>
* Vertical, violent selling
┌─────────────────────────────────────────────────────┐
* Deep structural break
│  FAB FOUR ELEMENTS                                  │
* Institutional liquidation
├─────────────────────────────────────────────────────┤
│  1. Previous Day High/Low (PDHL)                    │
│  2. 21-Period Moving Average                        │
│  3. 200-Period Moving Average                      │
│  4. Yesterday's Close                              │
└─────────────────────────────────────────────────────┘
</pre>
 
=== MA is a ZONE, Not a Line ===
 
{{quote|The MA is a zone, not a thin line. Don't be exact with this.}}
 
<syntaxhighlight lang="python">
# File: signal_generation_trade_management.py:68
ma_buffer_points: float = 25.0  # 21 MA zone width (not a thin line)
</syntaxhighlight>
 
=== Fab Four Tightness = Explosive Potential ===
 
When the Fab Four elements are '''tight together''':
* Indicates compressed energy
* Expect '''powerful move''' (up or down)
* Best trades come from '''narrowness'''


----
----


== Identifying Market Tops ==
== 2.2 Entry Position Hierarchy ==
 
=== Best Entry Positions ===


Major tops usually show 2+ of the following:
<pre>
FOR SHORTS:
┌─────────────────────────────────────────────────────┐
│  CEILING (Best short position)                      │
│  ═══════════════════════════════════════════        │  ← Price right under Fab Four
│  Price opens HERE                                  │
└─────────────────────────────────────────────────────┘


# 3–5 leg run-up
FOR LONGS:
# Vertical acceleration in final leg
┌─────────────────────────────────────────────────────┐
# Exhaustion bar
│  Price opens HERE                                  │
# Three-Finger Spread (Price–MA21–MA200)
│  ═══════════════════════════════════════════        │  ← Price right above Fab Four
│  FLOOR (Best long position)                        │
└─────────────────────────────────────────────────────┘
</pre>
 
=== Multi-Timeframe Alignment ===
 
Check all timeframes simultaneously:
 
<pre>
┌────────┬────────┬────────┬────────┐
│  2min  │  5min  │  15min │  Daily │
│  ────  │  ────  │  ────  │  ────  │
│ Under  │ Under  │ Under  │ Under  │
│  200  │  200  │  200  │  200  │
│ Tight  │ Tight  │ Tight  │ Tight  │
└────────┴────────┴────────┴────────┘
        = ALIGNED = HIGH QUALITY SETUP
</pre>
 
=== Code Implementation ===
<syntaxhighlight lang="python">
# File: setup_quality_detection.py:43-48
timeframe_alignment_weight: float = 0.30  # 30% of setup quality score
</syntaxhighlight>
 
----
 
== 2.3 Bar-by-Bar vs Big Bar Stops ==
 
=== The Rule ===
 
{| class="wikitable"
! When to Use !! Stop Method !! Why
|-
| '''Near MA''' (hugging) || Big Bar stops || Eliminates noise
|-
| '''Far from MA''' (extended) || Bar-by-bar stops || Protect extended gains
|}
 
=== The Warning ===
 
{{quote|Bar-by-bar will knock you out of riches. If there is one stopout that is going to knock you out of the biggest gains of your life, it's going to be bar-by-bar.}}
 
'''Use bar-by-bar ONLY when:'''
* Price has moved significantly away from MA
* "You had better be moving to Pluto"
* Slant on both 2min and 5min is sharp
 
----
 
= Part 3: Stop Loss Methodology =
 
== 3.1 Stop Placement Hierarchy ==
 
=== Two Stop Options ===
 
{| class="wikitable"
! Type !! Description !! When to Use
|-
| '''Event Stop''' || Based on price action event || Primary choice
|-
| '''Maximum Stop''' || Dollar-based max loss || Fallback when event too far
|}
 
=== The Goal ===


<pre>
<pre>
three_finger_spread_threshold = 0.02
┌─────────────────────────────────────────────────────┐
│  FAB FOUR ZONE (Helping Zone)                      │
├─────────────────────────────────────────────────────┤
│  ↑ STOP SHOULD BE HERE (above/below Fab Four)      │
├─────────────────────────────────────────────────────┤
│  Entry price                                        │
└─────────────────────────────────────────────────────┘
</pre>
</pre>
{{quote|The real goal is to get your stop beyond the Fab Four helping zone.}}
=== Code Implementation ===
<syntaxhighlight lang="python">
# File: signal_generation_trade_management.py:59-60
min_stop_distance: float = 40.0    # TICKET-13: Increased from 20
default_stop_distance: float = 40.0  # Minimum buffer for price noise
</syntaxhighlight>


----
----


== Entry Methodology ==
== 3.2 Stop and Reverse Rules ==


=== The Fab Four ===
Three criteria for a valid '''Stop and Reverse''':
* Previous Day High/Low
 
* 21-period MA
{| class="wikitable"
* 200-period MA
! Criteria !! Description
* Yesterday’s Close
|-
| '''1. Immediate''' || Stop out happens INSTANTLY, not gradually
|-
| '''2. Violent''' || Move that stops you is hard, powerful, shakes earth
|-
| '''3. Decent Position''' || New position is NOT into resistance/support
|}


MA is treated as a zone, not a line.
=== Invalid Stop and Reverse ===


<pre>
<pre>
ma_buffer_points = 25.0
❌ Going LONG right INTO the 200 MA
❌ Going LONG right INTO tight Fab Four zone
❌ Going SHORT right INTO strong support
 
Even if immediate + violent, bad position = no reversal
</pre>
</pre>


=== Entry Hierarchy ===
=== Code Implementation ===
* Shorts → price just below Fab Four (ceiling)
<syntaxhighlight lang="python">
* Longs → price just above Fab Four (floor)
# File: signal_generation_trade_management.py:80-81
bos_structure_lookback: int = 10  # TICKET-11: Extended for BOS stops
bos_stop_buffer_points: float = 5.0  # Buffer for structure-based stops
</syntaxhighlight>


=== Multi-Timeframe Alignment ===
----
2m, 5m, 15m, Daily alignment = high-quality setup
 
= Part 4: Color Change Confirmation =
 
== 4.1 The Color Change Entry ==
 
=== Entry Trigger ===
<pre>
FOR SHORTS:
Red bar closes BELOW green bar's low → ENTER SHORT
Stop: Above the high
 
FOR LONGS:
Green bar closes ABOVE red bar's high → ENTER LONG
Stop: Below the low
</pre>
 
=== Key Rule: Don't Wait for Bar to Complete ===
 
{{quote|As soon as the red bar crosses below the green, boom boom boom boom boom. You're in.}}


----
----


== Stop Loss Methodology ==
== 4.2 Profit Taking Rules ==


=== Stop Types ===
=== The Two-Bar Rule ===
* Event-based stop (preferred)
* Maximum loss stop (fallback)


Goal: Stop beyond Fab Four helping zone.
{{quote|Take profits TWO bars after the opposite color, NOT one bar.}}


<pre>
<pre>
min_stop_distance = 40
SHORT TRADE:
default_stop_distance = 40
┌─────────────────────────────────────────────────────┐
│  GREEN bar (opposite color)                        │
├─────────────────────────────────────────────────────┤
│  RED bar 1 ← IGNITING bar (DO NOT take profit)      │
├─────────────────────────────────────────────────────┤
│  RED bar 2 ← FOLLOW-THROUGH bar (TAKE PROFIT)      │
└─────────────────────────────────────────────────────┘
</pre>
</pre>
=== Position Management Flow ===
<pre>
Step 1: Enter with 2 lots
Step 2: Set stop above high
Step 3: Take profit on 1 lot (first follow-through bar)
Step 4: Move stop to break-even
Step 5: Take profit on remaining lot (second follow-through)
Step 6: Done
</pre>
{{quote|The first lot is your REAL trade. The second lot is the cherry on top.}}
=== Code Implementation ===
<syntaxhighlight lang="python">
# File: signal_generation_trade_management.py:111-118
enable_color_change_filter: bool = False    # DISABLED - too restrictive
color_change_ma_proximity: float = 20.0      # Points to consider "near" MA
require_ma_bounce: bool = False              # Don't require strict MA bounce
</syntaxhighlight>


----
----


== Trading Glossary (Engineer-Friendly) ==
== 4.3 The Traffic Jam Concept ==
 
When price gaps below '''everything from prior day''':
 
<pre>
┌─────────────────────────────────────────────────────┐
│  Yesterday's 200 MA                                │
│  Yesterday's 20 MA                                  │
│  Yesterday's Close                                  │
│  ═══════════════════════════════════════════        │
│  TRAFFIC JAM ZONE (resistance on any rally)        │
│  ═══════════════════════════════════════════        │
│                                                    │
│  TODAY'S GAP DOWN OPEN                              │
└─────────────────────────────────────────────────────┘
</pre>
 
'''Rule''': Any move UP into the traffic jam meets resistance. Short rallies into this zone.
 
----
 
= Part 5: Trading Glossary for Engineers =


{| class="wikitable"
{| class="wikitable"
! Term !! Meaning !! Why It Matters
! Trading Term !! System Translation !! Code Location !! Why It Matters
|-
| '''Creeper Move''' || Small-bodied bars, consistent direction, low volume || <code>market_state_analysis.py:is_creeper_move</code> || Institutional accumulation before explosion. '''PENALTY: -50 points'''
|-
| '''Railroad Trend''' || Alternating green/red bars touching MA || <code>market_state_analysis.py:is_railroad_trend</code> || Healthy trend, not overextended. '''BONUS: +15 points'''
|-
|-
| Creeper Move || Small bars, quiet trend || Reversal risk
| '''Two-Day Trend''' || Price consistently above/below MA for 2+ days || <code>market_state_analysis.py:has_two_day_trend</code> || Confirms trend maturity. '''Required for A+ grade'''
|-
|-
| Railroad Trend || Alternating bars near MA || Healthy trend
| '''Institutional Fight''' || High volume with narrow range || <code>market_state_analysis.py:institutional_fight_in_progress</code> || Buyers vs sellers battle. '''MULTIPLIER: 0.7x score'''
|-
|-
| Two-Day Trend || Sustained MA bias || A+ requirement
| '''Discount Zone''' || Price below 21 MA (for longs) || <code>probability_zone_analysis.py</code> || 80% continuation probability
|-
|-
| Crash Bar || >2x bar size || Structural break
| '''Premium Zone''' || Price above 21 MA (for shorts) || <code>probability_zone_analysis.py</code> || Entry zone for short trades
|-
|-
| Fab Four || Key reference levels || Stop logic
| '''Fab Four''' || PDHL, 21 MA, 200 MA, Yesterday's Close || <code>signal_generation.py:_calculate_stop_loss()</code> || Stop loss placement hierarchy
|-
| '''Color Change''' || Bar closes opposite color after move || <code>probability_zone_analysis.py:ColorChangeDetector</code> || Confirms reversal/continuation
|-
| '''Break of Structure (BOS)''' || Price closes beyond recent swing H/L || <code>market_state_analysis.py:bos_detected</code> || Confirms trend continuation/reversal
|-
| '''MA Zone''' || MA is a band, not thin line (21 MA +/- 25pts) || <code>signal_generation.py:ma_buffer_points=25</code> || "Fab Four" concept from philosophy
|-
| '''Trend Phase''' || EARLY / MIDDLE / LATE classification || <code>market_state_analysis.py:trend_phase</code> || MIDDLE phase = optimal entry timing
|-
| '''Crash Bar''' || Bar > 2x average size, violent || <code>probability_zone_analysis.py:crash_bar_multiplier</code> || Structural break indicator
|-
| '''Traffic Jam''' || Yesterday's price activity zone || Conceptual || Resistance zone for gaps
|-
| '''Three-Finger Spread''' || Large gap between Price, 21 MA, 200 MA || <code>signal_generation.py:three_finger_spread_threshold</code> || Market top indicator
|}
|}


----
----


== System Architecture Overview ==
= Part 6: Component Architecture =
 
== 6.1 Pipeline Flow ==


<pre>
<pre>
Data → Trend → Market State Setup Quality → Signal → Execution
┌─────────────────┐  ┌───────────────────┐  ┌────────────────────┐
│  Data Manager  │ │  Trend Analysis  │ │  Market State     │
│  (1M/5M/1H/1D)  │  │  (MA21, MA200)    │  │  (7 Detections)    │
└─────────────────┘  └───────────────────┘  └────────────────────┘
                                                      ↓
┌─────────────────┐  ┌───────────────────┐  ┌────────────────────┐
│  Trade Exec    │ ← │  Signal Gen      │ ← │  Setup Quality     │
│  (P&L, Costs)  │  │  (Entry/Exit)    │  │  (5-Factor Score)  │
└─────────────────┘  └───────────────────┘  └────────────────────┘
</pre>
</pre>


----
----


== Setup Quality Scoring ==
== 6.2 Setup Quality Detection ==
 
'''File''': <code>src/components/setup_quality_detection.py</code>
 
=== 5-Factor Weighted Scoring System ===
 
{| class="wikitable"
! Factor !! Weight !! What It Measures
|-
| Timeframe Alignment || '''30%''' || All timeframes agree on direction
|-
| Trend Strength || '''20%''' || Healthy trend without warnings
|-
| Entry Quality || '''15%''' || Entry near MA, clean execution
|-
| Key Level Proximity || '''20%''' || Entry near support/resistance
|-
| Risk/Reward || '''15%''' || Favorable profit potential
|}
 
=== Penalty System ===


{| class="wikitable"
{| class="wikitable"
! Factor !! Weight
! Condition !! Penalty !! Trading Reason
|-
| Creeper Move || -50 pts || Quiet accumulation = reversal coming
|-
|-
| Timeframe Alignment || 30%
| MA Struggle || -30 pts || Price can't break MA = weak trend
|-
|-
| Trend Strength || 20%
| No Two-Day Trend || -30 pts || Trend not confirmed
|-
|-
| Entry Quality || 15%
| Wrong Trend Phase || -25 pts || Too early or too late in trend
|-
|-
| Key Levels || 20%
| Not Near MA || -40 pts || Entry too far from edge
|-
|-
| Risk/Reward || 15%
| Institutional Fight || 0.7x || Wait for resolution
|}
|}


=== Grade Thresholds ===
=== Grade Thresholds ===
* A+ 90 → Auto
 
* A ≥ 80 → Auto
{| class="wikitable"
* B–D ≥ 60 → Manual
! Grade !! Score !! Position Size !! Auto-Trade?
* F < 50 → Skip
|-
| A+ || >= 90 || 2 lots || Yes
|-
| A || >= 80 || 1 lot || Yes
|-
| B || >= 70 || 1 lot || No
|-
| C || >= 60 || 1 lot || No
|-
| D || >= 50 || 1 lot || No
|-
| F || < 50 || 1 lot || No
|}
 
----
 
== 6.3 Market State Analysis ==
 
'''File''': <code>src/components/market_state_analysis.py</code>
 
=== 7 Detection Algorithms ===
 
{| class="wikitable"
! # !! Algorithm !! What It Detects !! Trading Implication
|-
| 1 || Railroad Trend || Healthy alternating bars || +15 bonus, trend continuation likely
|-
| 2 || Creeper Move || Small bars, consistent direction || -50 penalty, reversal imminent
|-
| 3 || Volatility Calc || ATR-based regime || Adjust stop distance
|-
| 4 || Market State || TRENDING / SIDEWAYS / VOLATILE || Different strategy rules
|-
| 5 || Two-Day Trend || Multi-day momentum || Required for A+ grade
|-
| 6 || Trend Phase || EARLY / MIDDLE / LATE || MIDDLE = optimal entry
|-
| 7 || Institutional Behavior || Volume + price patterns || Fight = wait, Accumulation = prepare
|}
 
----
 
== 6.4 Signal Generation ==
 
'''File''': <code>src/components/signal_generation_trade_management.py</code>
 
=== Entry Filters Applied ===
 
{| class="wikitable"
! Filter !! Config Key !! Purpose
|-
| Hour Filter || <code>blocked_hours: [9, 22, 23]</code> || Block loss-making hours
|-
| MA Direction || <code>enable_ma_direction_filter: True</code> || LONG only if MA rising
|-
| Probability Zone || <code>enable_probability_zone_filter: True</code> || Entry in favorable zones
|-
| Color Change || <code>enable_color_change_filter: False</code> || Disabled (too restrictive)
|}
 
----
 
= Part 7: Branch Changes (service/backtest → rikk_mtf_backtest001) =
 
== 7.1 Complete Git Diff Summary ==
 
'''Total Changes''': 65 files changed across core source, scripts, and data
 
=== Modified (M) Source Files ===
{| class="wikitable"
! File !! Type !! Key Changes
|-
| <code>signal_generation_trade_management.py</code> || Component || TICKET-7,8,10,11,12,13,18,19,20,21,24 + PDF fixes + Grading fix
|-
| <code>trade_execution_engine.py</code> || Component || TICKET-9,13,15,17,20: Trailing stop, breakeven, ATR
|-
| <code>market_state_analysis.py</code> || Component || TICKET-25: 5MIN → 1HOUR data
|-
| <code>setup_quality_detection.py</code> || Component || TICKET-5: Position sizing fix
|-
| <code>timeframe_conversion.py</code> || Core || Date column fix, 1m skip, emoji removal
|-
| <code>data_structures.py</code> || Core || TICKET-15: <code>current_stop_price</code> field
|-
| <code>multi_timeframe_analysis.py</code> || Component || Whitespace cleanup
|-
| <code>main.py</code> || Entry || TICKET-12 config, emoji removal
|}
 
=== Added (A) Files ===
{| class="wikitable"
! File !! Purpose
|-
| <code>probability_zone_analysis.py</code> || '''NEW''': Implements trade_philosophy.pdf (974 lines)
|-
| <code>50+ scripts/analyze_*.py</code> || Analysis scripts for hypothesis building
|}
 
----
 
== 7.2 JIRA Ticket Fixes (Complete Details) ==
 
=== TICKET-5: Position Sizing Fix ===
'''File''': <code>setup_quality_detection.py:544-567</code>
 
'''Problem''': Previous sizing = 100-200 lots = Rs 5.7 Crore exposure on Rs 1 lakh capital (5700x!)
 
<syntaxhighlight lang="python">
# BEFORE (service/backtest):
multipliers = {
    SetupQualityGrade.A_PLUS: 200,  # 200 lots (impossible!)
    SetupQualityGrade.A: 150,
    SetupQualityGrade.B: 100,
    # ...
}
 
# AFTER (rikk_mtf_backtest001):
position_sizes = {
    SetupQualityGrade.A_PLUS: 2,    # 2 lots (Rs 1.14L exposure - realistic)
    SetupQualityGrade.A: 1,        # 1 lot
    SetupQualityGrade.B: 1,
    SetupQualityGrade.C: 1,
    SetupQualityGrade.D: 1,
    SetupQualityGrade.F: 1
}
</syntaxhighlight>
 
----
 
=== TICKET-7: R:R Preservation After Slippage ===
'''File''': <code>signal_generation_trade_management.py:241-285</code>
 
'''Problem''': Slippage moved entry but stop/target stayed fixed = corrupted R:R ratio
 
<syntaxhighlight lang="python">
# BEFORE: Stop and target not adjusted after slippage
actual_execution_price = execution_price + market_slippage  # Entry moved
# BUT stop_loss_price and take_profit_price stayed at original levels!
# RESULT: R:R became inverted (target closer than stop)
 
# AFTER: Shift stop and target with entry to maintain R:R
# Example (LONG with +1.5 pts slippage):
#  Before: entry=5710, stop=5680, target=5740 (30 pts each, 1:1 R:R)
#  After slippage: entry=5711.5, stop=5680, target=5740
#  WRONG R:R: stop=31.5 pts, target=28.5 pts (INVERTED!)
#  FIX: entry=5711.5, stop=5681.5, target=5741.5 (30 pts each, 1:1 R:R)
 
if signal.direction == Direction.LONG:
    actual_execution_price = execution_price + market_slippage
    # TICKET-7: Shift stop and target UP by slippage to maintain R:R
    adjusted_stop_loss = signal.stop_loss_price + market_slippage
    adjusted_take_profit = signal.take_profit_price + market_slippage
else:  # SHORT
    actual_execution_price = execution_price - market_slippage
    # TICKET-7: Shift stop and target DOWN by slippage to maintain R:R
    adjusted_stop_loss = signal.stop_loss_price - market_slippage
    adjusted_take_profit = signal.take_profit_price - market_slippage
</syntaxhighlight>
 
----
 
=== TICKET-8: CTT Rate Fix ===
'''File''': <code>signal_generation_trade_management.py:48-55</code>
 
'''Problem''': CTT was 0.05% (5x too high!). Dhan broker calculates Rs 52 on Rs 5.2L = 0.01%
 
<syntaxhighlight lang="python">
# BEFORE:
transaction_tax_rate: float = 0.000500  # 0.05% - WRONG!
 
# AFTER:
# MCX CTT = 0.01% on SELL side only. Since code charges at entry+exit,
# use 0.005% per leg so round-trip = 0.01% total (matches actual CTT)
# Dhan verified: CTT Rs 52 on Rs 5,20,000 sell value = 0.01%
transaction_tax_rate: float = 0.000050  # 0.005% per leg × 2 = 0.01% total
</syntaxhighlight>
 
----
 
=== TICKET-9: Market Impact Slippage Cap ===
'''File''': <code>trade_execution_engine.py:40-42, 585-605</code>
 
'''Problem''': 100 lots × 0.1 = 10 pts slippage (excessive!)
 
<syntaxhighlight lang="python">
# BEFORE: No cap on market impact
size_impact = signal.position_size * self.config.market_impact_factor
 
# AFTER: Cap to prevent excessive slippage
max_market_impact_slippage: float = 2.0  # Maximum 2 points
 
raw_size_impact = signal.position_size * self.config.market_impact_factor
size_impact = min(raw_size_impact, self.config.max_market_impact_slippage)
 
# For 1-2 lots (after TICKET-5 fix):
#  - base: 1.0 pts
#  - market_impact: min(1×0.1, 2.0) = 0.1 pts (capped at 2.0)
#  - volatility: 0.5 pts
#  - total: ~1.6 pts (realistic for MCX crude)
</syntaxhighlight>
 
----
 
=== TICKET-10: Entry Technique Alignment ===
'''File''': <code>signal_generation_trade_management.py:2012-2140</code>
 
'''Problem''': Entry technique logic didn't match strategy_engine.py priority order
 
<syntaxhighlight lang="python">
# COMPLETE REWRITE of _determine_entry_technique():
# BEFORE: Random priority order, creeper before BOS, missing key level checks
 
# AFTER (aligned with strategy_engine.py::_classify_entry_technique_exact()):
# PRIORITY 1: Creeper move → NEAR_MA (NOT green_bar/red_bar!)
# PRIORITY 2: BOS detected → BOS_ENTRY (only if NOT creeper)
# PRIORITY 3: Near key level → DISCOUNT_ZONE / BREAKOUT_PULLBACK
# PRIORITY 4: Near MA → MA_BOUNCE
# PRIORITY 5: Two-day trend → TWO_GREEN_DAILY / TWO_RED_DAILY
# PRIORITY 6: Railroad trend → GREEN_BAR_AFTER_PULLBACK / RED_BAR_AFTER_RALLY
# PRIORITY 7: Fallback → NEAR_MA
</syntaxhighlight>
 
----
 
=== TICKET-11: BOS Stop Settings ===
'''File''': <code>signal_generation_trade_management.py:78-81</code>
 
'''Problem''': 5-bar lookback + no buffer = stop too close in trending markets = 66.7% stop rate
 
<syntaxhighlight lang="python">
# BEFORE:
structure_lookback: int = 5  # Too short for BOS
 
# AFTER:
bos_structure_lookback: int = 10    # Extended lookback for BOS stops
bos_stop_buffer_points: float = 5.0  # Buffer below/above structure
</syntaxhighlight>
 
----
 
=== TICKET-12: Hour Filter ===
'''File''': <code>signal_generation_trade_management.py:83-93, 126-137, 571-581</code>
 
'''Problem''': Certain hours consistently lose money
 
<syntaxhighlight lang="python">
# NEW CONFIGURATION:
enable_hour_filter: bool = True
blocked_hours: [9, 22, 23]  # Block 9-10 AM and after 10 PM
 
# Data-driven analysis showed (from 1439 trades):
# Worst hours: 15(-Rs244K), 22(-Rs209K), 09(-Rs199K), 21(-Rs101K), etc.
# Profitable hours: 16, 17, 18, 19, 23 (total +Rs341K)
 
# Applied in generate_signal():
if self.config.enable_hour_filter and self.config.blocked_hours:
    current_hour = current_timestamp.hour
    if current_hour in self.config.blocked_hours:
        return None  # No signal during blocked hours
</syntaxhighlight>
 
----
 
=== TICKET-13: Minimum Stop Distance ===
'''File''': <code>signal_generation_trade_management.py:57-60, 852-870</code>
 
'''Problem''': 20pt stops hit too frequently due to normal price noise
 
<syntaxhighlight lang="python">
# BEFORE:
default_stop_distance: float = 20.000000
 
# AFTER:
min_stop_distance: float = 40.000000    # Minimum stop distance
default_stop_distance: float = 40.000000  # Default increased
 
# ENFORCEMENT in generate_signal():
# TICKET-13 FIX: ENFORCE MINIMUM STOP DISTANCE (40 POINTS)
stop_distance = max(calculated_stop_distance, self.config.min_stop_distance)
</syntaxhighlight>
 
----
 
=== TICKET-15: Trailing Stop Tracking ===
'''File''': <code>data_structures.py:2982-2984</code>, <code>trade_execution_engine.py:54-70, 295-392</code>
 
'''Problem''': No way to track current trailing stop position vs original
 
<syntaxhighlight lang="python">
# NEW FIELD in Trade dataclass:
current_stop_price: Optional[float] = None  # Current trailing stop (moves with price)
 
# NEW METHOD in TradeExecutionEngine:
def _update_trailing_stop(self, trade: Trade, current_high: float, current_low: float):
    """
    TICKET-15/17/20: Update stop based on price movement.
 
    Two-Phase Stop Management:
    PHASE 1 - Breakeven (TICKET-17): Move stop to entry when profitable
    PHASE 2 - Trailing (TICKET-15/20): Trail stop behind price
    """
    if trade.current_stop_price is None:
        trade.current_stop_price = trade.original_stop_price
 
    # Calculate trailing distance (ATR-based or fixed)
    if self.config.trailing_stop_method == "ATR_MULTIPLE":
        trailing_distance = self.current_atr * self.config.atr_multiplier
        trailing_distance = max(trailing_distance, 15.0)  # Min 15 pts for Crude
    else:
        trailing_distance = self.config.trailing_stop_distance
 
    if trade.direction == Direction.LONG:
        current_profit = current_high - trade.entry_price
        if current_profit >= self.config.trailing_stop_activation:
            new_stop = current_high - trailing_distance
            if new_stop > trade.current_stop_price:
                trade.current_stop_price = new_stop  # Only move UP
</syntaxhighlight>
 
----
 
=== TICKET-17: Breakeven Stop ===
'''File''': <code>trade_execution_engine.py:64-68</code>
 
'''Problem''': Needed automatic breakeven move when in profit
 
<syntaxhighlight lang="python">
# NEW CONFIGURATION:
enable_breakeven_stop: bool = True
breakeven_activation: float = 25.0  # Points profit before moving to breakeven
breakeven_buffer: float = 2.0      # Points above/below entry for buffer
 
# Tested 10pt activation but cut winners too short (26% WR vs 49%)
# 25pt activation is the sweet spot
</syntaxhighlight>
 
----
 
=== TICKET-18: Creeper Move Handling ===
'''File''': <code>signal_generation_trade_management.py:582-595</code>
 
'''Problem''': Previous implementation blocked creeper signals entirely (too aggressive)
 
<syntaxhighlight lang="python">
# BEFORE: Creeper signals blocked with return None
 
# AFTER (comment explains fix):
# CORE BEHAVIOR: Creeper moves get -50 penalty + 0.7x target + uses NEAR_MA
# Previous implementation: Blocked entirely with return None (too aggressive)
#
# FIX: Let creeper signals through - penalty applied in setup_quality_detection,
# NEAR_MA technique used in _determine_entry_technique()
# Let the scoring system decide rather than blocking outright
</syntaxhighlight>
 
----
 
=== TICKET-19: MA Direction Filter + Score Adjustment ===
'''File''': <code>signal_generation_trade_management.py:95-97, 987-1034, 1955-2010</code>
 
'''Problem''': Trades against MA21 slope direction had poor performance
 
<syntaxhighlight lang="python">
# CONFIGURATION:
enable_ma_direction_filter: bool = True
 
# DIRECTION LOGIC COMPLETE REWRITE (_determine_signal_direction):
# BEFORE: Used alignment score threshold (>= 60%)
# AFTER: Uses MA21 slope as primary direction source
 
def _determine_signal_direction(self, timeframe_analysis, market_state, market_data=None):
    """MA21 SLOPE ALIGNMENT DIRECTION LOGIC (trade_philosophy.pdf)"""
    trend_direction = getattr(market_state, 'trend_direction', None)
 
    if trend_direction == "up":
        return Direction.LONG      # MA21 rising → only LONG
    elif trend_direction == "down":
        return Direction.SHORT    # MA21 declining → only SHORT
    else:
        # Fallback to MTF primary_direction if MA21 is flat/unknown
        return getattr(timeframe_analysis, 'primary_direction', None)
 
# SCORE ADJUSTMENT (lines 987-1034):
# +15% bonus if trade direction aligns with MA21 slope
# -10% penalty if trade direction against MA21 slope
</syntaxhighlight>
 
----
 
=== TICKET-20: Probability Zone Filter + ATR Trailing ===
'''File''': <code>signal_generation_trade_management.py:99-109, 628-817</code>, <code>trade_execution_engine.py:57-63, 295-340</code>
 
'''Problem''': Needed trade_philosophy.pdf concepts in code
 
<syntaxhighlight lang="python">
# NEW CONFIGURATION (Probability Zones):
enable_probability_zone_filter: bool = True
probability_zone_swing_lookback: int = 20
probability_zone_min_range: float = 20.0
three_finger_spread_threshold: float = 0.02
crash_bar_multiplier: float = 2.0
sideways_mean_reversion: bool = True
 
# NEW CONFIGURATION (ATR Trailing):
trailing_stop_method: str = "ATR_MULTIPLE"  # or "FIXED_POINTS"
atr_period: int = 14
atr_multiplier: float = 2.0  # 2x ATR = trailing distance
 
# NEW ATR CALCULATION in trade_execution_engine.py:295-340
def _calculate_atr(self, five_min_data: Dict) -> None:
    """Calculate Average True Range for dynamic trailing stop."""
    # TrueRange = max(high-low, abs(high-prev_close), abs(low-prev_close))
    # ATR = SMA(TrueRange, period)
    true_ranges = []
    for i in range(1, len(high_vals)):
        tr = max(
            high_vals[i] - low_vals[i],          # Current high - low
            abs(high_vals[i] - close_vals[i-1]),  # High - previous close
            abs(low_vals[i] - close_vals[i-1])    # Low - previous close
        )
        true_ranges.append(tr)
    self.current_atr = sum(true_ranges) / len(true_ranges)
</syntaxhighlight>
 
----
 
=== TICKET-21: Color Change Filter (DISABLED) ===
'''File''': <code>signal_generation_trade_management.py:111-118</code>
 
'''Problem''': color_change.pdf patterns too restrictive for automation
 
<syntaxhighlight lang="python">
# CONFIGURATION (disabled):
enable_color_change_filter: bool = False  # DISABLED - too restrictive
color_change_ma_proximity: float = 20.0  # Points to consider "near" MA
require_ma_bounce: bool = False          # Too strict
color_change_require_in_zones: bool = True
 
# NOTE: ColorChangeDetector class still exists for future use
# Implements liquidity sweep patterns:
# - LONG: Green bar sweeps BELOW red bar low + bounce from 21 MA
# - SHORT: Red bar sweeps ABOVE green bar high + rejection from 21 MA
</syntaxhighlight>
 
----
 
=== TICKET-24: Creeper Move Entry Technique Fix ===
'''File''': <code>signal_generation_trade_management.py:2037-2050</code>
 
'''Problem''': strategy_engine.py bug - uses wrong entry technique for creeper moves
 
<syntaxhighlight lang="python">
# STRATEGY ENGINE BUG FOUND:
# backtesting_standalone/src/strategy_engine.py lines 3338-3380
# checks bos_detected FIRST but doesn't consider is_creeper_move.
# This causes BOS entries in creeper moves (inappropriate).
 
# FIX: Check creeper FIRST before BOS
if is_creeper:
    # Creeper gets -50 penalty + 0.7x target from setup_quality_detection
    # But uses NEAR_MA as technique (NOT green_bar/red_bar!)
    return EntryTechnique.NEAR_MA  # Strategy engine fallback
</syntaxhighlight>
 
----
 
=== TICKET-25: Market State 5MIN → 1HOUR ===
'''File''': <code>market_state_analysis.py:191-360</code>
 
'''Problem''': Creeper threshold 0.5% calibrated for 1H bars (~0.8-1.2% range), but code used 5MIN (~0.16% range) = 98.9% false positives!
 
<syntaxhighlight lang="python">
# BEFORE:
required_tf = TimeframeValue.FIVE_MIN
 
# AFTER:
def validate_input(self, input_data: Dict, context: ComponentContext):
    """
    TICKET-25 FIX: Market state analysis uses 1-HOUR data (not 5MIN)
    to match strategy_engine.py behavior for creeper/railroad detection.
    """
    primary_tf = TimeframeValue.ONE_HOUR
    fallback_tf = TimeframeValue.FIVE_MIN
 
    if primary_tf in input_data and input_data[primary_tf] is not None:
        required_tf = primary_tf
    elif fallback_tf in input_data and input_data[fallback_tf] is not None:
        required_tf = fallback_tf
        # Warning: 5MIN fallback may cause inaccurate creeper detection
 
def _get_primary_timeframe(self, input_data: Dict) -> TimeframeValue:
    """
    TICKET-25 FIX: Use ONE_HOUR for market state analysis.
 
    The 0.5% creeper threshold is calibrated for 1-HOUR bars (~0.8-1.2% typical range),
    not 5-MIN bars (~0.16% typical range). Using 5MIN caused 98.9% false positives.
    """
    primary_tf = TimeframeValue.ONE_HOUR  # Was FIVE_MIN
</syntaxhighlight>
 
----
 
=== PDF-FIX: MA Buffer Points ===
'''File''': <code>signal_generation_trade_management.py:67-68</code>
 
'''Source''': Fab Four concept - "MA is a zone, not a thin line"
 
<syntaxhighlight lang="python">
# BEFORE:
ma_buffer_points: float = 5.000000  # Too tight!
 
# AFTER:
# PDF-FIX: MA is a "zone, not a thin line" (Fab Four) - use wider buffer
ma_buffer_points: float = 25.000000  # 21 MA zone width
</syntaxhighlight>
 
----
 
=== GRADING FIX: Score-to-Grade Recalculation ===
'''File''': <code>signal_generation_trade_management.py:1054, 1132-1170</code>
 
'''Problem''': Grade assigned from capped original score instead of adjusted score
 
<syntaxhighlight lang="python">
# BEFORE:
setup_quality=setup_quality.grade,    # Grade from CAPPED original score (79)
setup_score=setup_quality.score,      # Original score (79)
# Problem: Score=79 → Grade=A, but if adjustment makes it 89, should be A+!
 
# AFTER:
setup_quality=self._calculate_grade_from_score(adjusted_score),  # RECALCULATED
setup_score=adjusted_score,  # MA-adjusted score
 
# NEW METHOD ADDED:
def _calculate_grade_from_score(self, score: float) -> SetupQualityGrade:
    """GRADING FIX: Calculate grade from FINAL adjusted score."""
    if score >= 90: return SetupQualityGrade.A_PLUS
    elif score >= 80: return SetupQualityGrade.A
    elif score >= 70: return SetupQualityGrade.B
    elif score >= 60: return SetupQualityGrade.C
    elif score >= 50: return SetupQualityGrade.D
    else: return SetupQualityGrade.F
</syntaxhighlight>
 
----
 
== 7.3 New File: probability_zone_analysis.py (974 lines) ==
 
This file implements concepts from <code>trade_philosophy.pdf</code>:
 
=== Enums Defined ===
<syntaxhighlight lang="python">
class ProbabilityZone(Enum):
    TOP_THIRD = "top_third"          # 80% continuation probability
    TOP_HALF = "top_half"            # 65% continuation probability
    BOTTOM_HALF = "bottom_half"      # 35% continuation probability
    BOTTOM_THIRD = "bottom_third"    # 15% continuation (85% reversal)
 
class MarketStructure(Enum):
    UPTREND = "uptrend"              # Price > 21 MA > 200 MA
    DOWNTREND = "downtrend"          # Price < 21 MA < 200 MA
    SIDEWAYS = "sideways"            # No clear structure
    THREE_FINGER_SPREAD_BULL = "..."  # Large spread (bearish signal)
    THREE_FINGER_SPREAD_BEAR = "..."  # Large spread (bullish signal)
 
class PullbackType(Enum):
    HEALTHY_PULLBACK = "healthy_pullback"  # 45-degree drift, holds above halfway
    COLLAPSE = "collapse"                  # Vertical drop, breaks deeply
    NO_PULLBACK = "no_pullback"            # Price at or near highs
    BOUNCE = "bounce"                      # Bounce after crash (short opportunity)
 
class ColorChangeType(Enum):
    BULLISH_REVERSAL = "bullish_reversal"  # Green bar takes out red bar high
    BEARISH_REVERSAL = "bearish_reversal"  # Red bar takes out green bar low
    NO_PATTERN = "no_pattern"
</syntaxhighlight>
 
=== Key Classes ===
* <code>ProbabilityZoneResult</code> - Analysis result with zone, probabilities, MA structure
* <code>ColorChangeResult</code> - Pattern detection result
* <code>ProbabilityZoneConfig</code> - Configuration with thresholds
* <code>ProbabilityZoneAnalyzer</code> - Main analyzer class
* <code>ColorChangeDetector</code> - Detects liquidity sweep patterns
 
=== Configuration Defaults ===
<syntaxhighlight lang="python">
@dataclass
class ProbabilityZoneConfig:
    top_third_probability: float = 0.80    # 80% continuation
    top_half_probability: float = 0.65    # 65% continuation
    bottom_half_probability: float = 0.35  # 35% continuation
    bottom_third_probability: float = 0.15 # 15% continuation
 
    swing_lookback_bars: int = 20          # Bars for swing H/L
    crash_bar_multiplier: float = 2.0      # Bar > 2x avg = crash
    three_finger_min_spread_pct: float = 0.02  # 2% spread threshold
</syntaxhighlight>
 
----
 
== 7.4 timeframe_conversion.py Changes ==
 
'''File''': <code>src/core/timeframe_conversion.py</code>
 
=== Changes ===
# '''Emoji removal''' - All emoji characters replaced with <code>[OK]</code>, <code>[FAIL]</code>, <code>[CONV]</code>, etc.
# '''Date column fix''' - Handle 'date' as alias for 'timestamp'
# '''1m skip''' - Don't overwrite source file when saving
# '''Mixed timestamp format''' - Use <code>format='mixed'</code> for pandas parsing
 
<syntaxhighlight lang="python">
# Date column alias:
if 'date' in source_df.columns and 'timestamp' not in source_df.columns:
    source_df = source_df.rename(columns={'date': 'timestamp'})
    logger.info("[FIX] Renamed 'date' column to 'timestamp'")
 
# Skip 1m overwrite:
if timeframe == '1m':
    logger.info(f"[SKIP] 1m: Source file preserved (not overwritten)")
    continue
 
# Mixed timestamp parsing:
pd.to_datetime(df['timestamp'], format='mixed')
</syntaxhighlight>
 
----
 
== 7.5 main.py Changes ==
 
'''File''': <code>src/main.py</code>
 
=== Changes ===
# '''Hour filter configuration''' - TICKET-12 support
# '''Emoji removal''' - Console output cleanup
 
<syntaxhighlight lang="python">
# TICKET-12: Hour Filter configuration:
enable_hour_filter=strategy_config.get('enable_hour_filter', False),
blocked_hours=strategy_config.get('blocked_hours', [])
 
print(f"  TICKET-12 Hour Filter: Enabled={signal_generator_config.enable_hour_filter}, "
      f"Blocked Hours={signal_generator_config.blocked_hours}")
</syntaxhighlight>
 
----
 
== 7.6 Complete File Tree ==
 
<pre>
services/backtest/src/
├── components/
│  ├── market_state_analysis.py      # TICKET-25: 5MIN 1HOUR
│  ├── multi_timeframe_analysis.py  # Whitespace cleanup
│  ├── probability_zone_analysis.py  # NEW: trade_philosophy.pdf (974 lines)
│  ├── setup_quality_detection.py    # TICKET-5: position sizing
│  ├── signal_generation_trade_management.py  # TICKET-7,8,10,11,12,13,18,19,20,21,24 + GRADING FIX
│  └── trade_execution_engine.py    # TICKET-9,13,15,17,20: trailing/breakeven/ATR
├── core/
│  ├── data_structures.py            # TICKET-15: current_stop_price field
│  └── timeframe_conversion.py      # Date fix, 1m skip, emoji removal
└── main.py                          # TICKET-12 config, emoji removal
 
services/backtest/scripts/          # 50+ NEW analysis scripts
├── analyze_alignment_pnl.py
├── analyze_alignment_pnl_v2.py
├── analyze_aplus.py
├── analyze_by_hour.py
├── analyze_combined_filters.py
├── analyze_crash_short_potential.py
├── analyze_hour_filter.py
├── analyze_hourly_pnl.py
├── analyze_long_short_detail.py
├── analyze_longs.py
├── analyze_ma_alignment.py
├── analyze_ma_slope_filter.py
├── analyze_morning_times.py
├── analyze_pdf_results.py
├── analyze_quick_exits.py
├── analyze_red_bar_rally.py
├── analyze_shorts.py
├── analyze_stop_exits.py
├── analyze_stop_loss_detail.py
├── analyze_test_summary.py
├── analyze_trade_bias.py
├── analyze_trading_hours_filter.py
├── analyze_trend_direction_at_entry.py
├── aplus_vs_a_analysis.py
├── check_all_data.py
├── check_costs.py
├── check_data_range.py
├── check_price_trend.py
├── comprehensive_analysis.py
├── comprehensive_backtest_analysis.py
├── comprehensive_summary.py
├── cost_impact_analysis.py
├── detailed_monthly.py
├── diagnose_color_change.py
├── diagnose_direction_bias.py
├── framework_comparison_analysis.py
├── generate_test_summary.py
├── grade_and_equity.py
├── monthly_breakdown.py
├── no_morning_analysis.py
├── path_to_profitability.py
├── philosophy_v1_blend_analysis.py
├── root_cause_summary.py
├── short_market_state_alignment.py
├── short_technique_analysis.py
├── simulate_target_rr.py
├── simulate_target_rr_v2.py
├── stop_out_deep_analysis.py
├── strategy_engine_gap_analysis.py
├── test_summary.py
└── v1_optimization_impact_analysis.py
</pre>
 
----
 
= Part 8: Strategy Configuration =
 
== 8.1 76D Parameter Vector ==
 
The strategy uses '''regime-aware configuration''' with 76 parameters:
* '''44 Global Parameters''' - Constant across all market regimes
* '''32 Regime Parameters''' - 8 parameters × 4 market regimes
 
'''File''': <code>src/config/strategy_config.py</code>
 
=== Key Parameters ===
 
{| class="wikitable"
! Parameter !! Default !! Description
|-
| <code>primary_ma_period</code> || 21 || Main trend MA
|-
| <code>secondary_ma_period</code> || 200 || Long-term trend MA
|-
| <code>default_stop_distance</code> || 40 pts || Minimum stop distance
|-
| <code>default_risk_reward</code> || 2.0 || Target R:R ratio
|-
| <code>ma_buffer_points</code> || 25 pts || MA zone width
|-
| <code>creeper_move_penalty</code> || -50 || Score reduction
|-
| <code>railroad_trend_bonus</code> || +15 || Score increase
|}
 
----
 
= Part 9: Decision Trees =
 
== 9.1 Should I Trade This Setup? ==
 
<pre>
START: Signal Generated
  │
  ▼
[Is hour blocked (9, 22, 23)?]
  │ Yes → SKIP (loss-making hours)
  │ No ↓
  ▼
[Is MA21 direction aligned with trade?]
  │ LONG + MA rising? → Continue
  │ SHORT + MA falling? → Continue
  │ No alignment → SKIP
  │
  ▼
[Is price in probability zone?]
  │ LONG + Bottom Third? → Continue (80% odds)
  │ SHORT + Top Third? → Continue (80% odds)
  │ Wrong zone → SKIP
  │
  ▼
[Calculate Setup Quality Score]
  │
  ├─ Apply 5-factor scoring (TF 30%, Trend 20%, Entry 15%, KeyLevel 20%, R:R 15%)
  ├─ Apply penalties (creeper -50, MA struggle -30, etc.)
  ├─ Apply institutional fight multiplier (0.7x)
  ├─ Apply MA direction adjustment (+15% aligned, -10% against)
  │
  ▼
[Recalculate Grade from ADJUSTED score]
  │
  ├─ A+ or A → Auto-trade eligible (2 lots for A+, 1 lot for A)
  ├─ B to D → Manual review (1 lot)
  ├─ F → Skip or minimal size
  │
  ▼
[Execute Trade with Position Size]
</pre>
 
----
 
== 9.2 Where to Place Stop? ==
 
<pre>
START: Trade Direction Determined
  │
  ▼
[Is Fab Four zone tight and close?]
  │ Yes → Place stop BEYOND Fab Four zone
  │ No ↓
  ▼
[Can I afford stop beyond Fab Four?]
  │ Yes → Use EVENT stop (beyond Fab Four)
  │ No → Use MAXIMUM loss stop ($6000 max)
  │
  ▼
[ENFORCE minimum 40pt stop (TICKET-13)]
  │
  ▼
[Once trade moves in favor:]
  │
  ├─ 25 pts profit → Move stop to breakeven (TICKET-17)
  ├─ 20+ pts profit → Start trailing (TICKET-15/20)
  ├─ Use ATR-based trail distance (2x ATR, min 15 pts)
  │
  ▼
[Stop Placement Complete]
</pre>
 
----
 
= Part 10: Code Review Guidelines =
 
== 10.1 What Reviewers Should Check ==
 
* Code correctness (syntax, bugs)
* Integration (doesn't break other components)
* Test coverage
* Precision (6-decimal places per spec)
* Performance (no excessive logging)
 
== 10.2 What Reviewers Should NOT Question ==
 
* The penalty values themselves (-50, -30, etc.)
* Why 21 MA and not 20 MA
* Why specific thresholds (these are trading decisions)
* Why certain hours are blocked
 
== 10.3 Trading Authority Principle ==
 
'''Rikk has final authority on:'''
* Entry/exit conditions
* Threshold values
* Setup definitions
* What constitutes a valid signal
* Penalty/bonus amounts
 
'''Engineers have authority on:'''
* Code quality and structure
* Performance optimization
* Error handling
* System integration
* Test coverage
 
----
 
= Part 11: Quick Reference Cards =
 
== Card 1: Probability Zones ==
 
<pre>
TOP THIRD    = 80% continuation (SHORT zone)
TOP HALF    = 65% continuation
BOTTOM HALF  = 35% continuation
BOTTOM THIRD = 15% continuation (LONG zone with 85% reversal odds)
</pre>
 
== Card 2: Setup Quality Formula ==
 
<pre>
Score = (TF_align × 0.30) + (Trend × 0.20) + (Entry × 0.15) + (KeyLevel × 0.20) + (R:R × 0.15)
 
Then apply:
- Creeper detected? → Score - 50
- MA struggle? → Score - 30
- No two-day trend? → Score - 30
- Wrong phase? → Score - 25
- Institutional fight? → Score × 0.7
- MA direction aligned? → Score + 15%
- MA direction against? → Score - 10%
 
Finally: Recalculate grade from ADJUSTED score (not original!)
</pre>
 
== Card 3: Profit Taking ==
 
<pre>
1. Enter with 2 lots
2. Set stop above high (short) / below low (long)
3. Wait for follow-through bar (2nd bar after opposite color)
4. Take profit on 1 lot
5. Move stop to break-even
6. Wait for next follow-through bar
7. Take profit on remaining lot
8. Done
</pre>
 
== Card 4: JIRA Tickets Summary ==
 
{| class="wikitable"
! Ticket !! One-Line Summary
|-
| TICKET-5 || Position sizing: 200 lots 2/1 lots (realistic for Rs 1L capital)
|-
| TICKET-7 || R:R preservation: shift stop/target with slippage
|-
| TICKET-8 || CTT rate: 0.05% → 0.005% per leg (5x fix)
|-
| TICKET-9 || Market impact: cap slippage at 2 pts max
|-
| TICKET-10 || Entry technique: align with strategy_engine.py priority order
|-
| TICKET-11 || BOS stops: 5 → 10 bar lookback + 5pt buffer
|-
| TICKET-12 || Hour filter: block hours 9, 22, 23 (loss-making)
|-
| TICKET-13 || Min stop: 20 → 40 pts (noise protection)
|-
| TICKET-15 || Trailing stop: add current_stop_price tracking
|-
| TICKET-17 || Breakeven: move stop to entry at 25pt profit
|-
| TICKET-18 || Creeper handling: let through (don't block), use penalty
|-
| TICKET-19 || MA direction: use slope as primary direction source
|-
| TICKET-20 || Probability zones + ATR trailing (trade_philosophy.pdf)
|-
| TICKET-21 || Color change: disabled (too restrictive)
|-
| TICKET-24 || Creeper entry: use NEAR_MA technique (not green/red bar)
|-
| TICKET-25 || Market state: 5MIN → 1HOUR for creeper detection
|-
| GRADING FIX || Recalculate grade from adjusted score
|-
| PDF-FIX || MA buffer: 5 → 25 pts (MA is zone, not line)
|}


----
----


''Last Updated: 2026-01-05 | Branch: rikk_mtf_backtest001 | Validated: 19-month backtest''
''Last Updated: 2026-01-05 | Branch: rikk_mtf_backtest001 | Validated: 19-month backtest''

Revision as of 20:17, 4 January 2026

Alpha Research: MCX Crude Oil MA21 Strategy

Single Source of Truth for the PlusEV Trading System


Quick Reference: Backtest Proof

Metric Value Notes
Total P&L Rs +25,48,101 19-month validation period
Win Rate 57.6% Above 55% threshold
Profit Factor 1.20 Risk-adjusted returns
Total Trades 7,534 Statistical significance
Initial Capital Rs 1,00,000 Starting portfolio
Final Capital Rs 26,48,101 2548% return

Branch: rikk_mtf_backtest001 | Commit: 68dae212

Template:Quote


Part 1: Core Trading Philosophy

1.1 Foundational Principles

Simple systems outperform complex ones.
Market behavior is probabilistic, not predictive.
The goal is positioning with asymmetric probabilities, not prediction.

The Asymmetric Probability Edge

When odds are low on one outcome, the opposite side usually carries high odds:

  • If new high probability drops to 15%, then 85% odds favor reversal
  • We position ourselves on the high-probability side

1.2 Probability Zones (Halves & Thirds)

Every large move is divided into halves and thirds, creating probability zones.

Odds of Continuation After Pullback

┌─────────────────────────────────────────────────────┐
│  SWING HIGH                                         │
├─────────────────────────────────────────────────────┤
│  TOP THIRD        →  ~80% chance of new high        │  ← IDEAL SHORT ZONE
├─────────────────────────────────────────────────────┤
│  TOP HALF         →  ~65% chance of new high        │
├─────────────────────────────────────────────────────┤
│  BOTTOM HALF      →  ~35% chance of new high        │
├─────────────────────────────────────────────────────┤
│  BOTTOM THIRD     →  ~15% chance of new high        │  ← IDEAL LONG ZONE
├─────────────────────────────────────────────────────┤
│  SWING LOW                                          │
└─────────────────────────────────────────────────────┘

Code Implementation

<syntaxhighlight lang="python">

  1. File: signal_generation_trade_management.py:99-109

enable_probability_zone_filter: bool = True probability_zone_swing_lookback: int = 20 # Bars to find swing H/L probability_zone_min_range: float = 20.0 # Min range for valid zone </syntaxhighlight>


1.3 The Crash Play (Core Strategy)

What is a Crash Bar?

  • Much larger than recent bars
  • Fast, violent, elongated movement
  • Indicates a structural break

The Crash Play Logic

1. Identify crash bar (bar > 2x average size)
2. Divide it into halves and thirds
3. Watch for bounce INTO these zones
4. Enter when:
   - Color change confirms (red overtakes green), OR
   - Price reaches upper zones

Key Statistics

  • After a crash, bounces have only ~15% odds of reclaiming highs
  • ~85% odds favor continuation lower
  • Bounces after crashes are statistically SHORT opportunities

Code Implementation

<syntaxhighlight lang="python">

  1. File: signal_generation_trade_management.py:108

crash_bar_multiplier: float = 2.0 # Bar must be 2x average for crash detection </syntaxhighlight>


1.4 Pullback vs Collapse (Critical Distinction)

Healthy Pullback (Tradeable)

Characteristic Description
Angle 45-degree drifting decline, NOT vertical
Bars No violent or oversized red bars
Depth Holds above halfway point of prior run
Confirmation Color change (green overtakes red)

Interpretation: Pullbacks are rests, not reversals. Odds favor continuation.

Collapse (NOT Tradeable)

Characteristic Description
Angle Vertical, elongated, violent first drop
Depth Breaks deeply into or below prior run
Momentum Abrupt and forceful

Interpretation: Indicates institutional selling. Bounces are sucker plays.


1.5 Identifying Market Tops (4 Characteristics)

Major tops usually exhibit at least 2 of these 4 characteristics:

1. Three-to-Five Leg Run-Up

Markets top between leg 3 and leg 5.
- Buy: legs 1-2
- Ride: leg 3
- Take profits: legs 4-5
- Buying late (leg 4-5) = large downside vs small upside

2. Vertical Acceleration in Final Leg

If the last leg is STEEPER than prior legs → likely final leg
The most vertical leg is usually the top.

3. Exhaustion Bar

Final bar of final leg is:
- Larger than recent bars
- Often the largest bar of entire run
= Bulls deploy all remaining buying power
= Market becomes top-heavy and vulnerable

4. Three-Finger Spread (Dual Space)

Large separation between:
- Price
- 21-period MA
- 200-period MA

= Many traders holding large unrealized profits
= Any red bar can trigger mass profit-taking
= Creates fast, violent declines

Code Implementation

<syntaxhighlight lang="python">

  1. File: signal_generation_trade_management.py:107

three_finger_spread_threshold: float = 0.02 # 2% min spread for detection </syntaxhighlight>


Part 2: Entry Methodology

2.1 The Fab Four Concept

The Fab Four defines the key reference points for entries and stops:

┌─────────────────────────────────────────────────────┐
│  FAB FOUR ELEMENTS                                  │
├─────────────────────────────────────────────────────┤
│  1. Previous Day High/Low (PDHL)                    │
│  2. 21-Period Moving Average                        │
│  3. 200-Period Moving Average                       │
│  4. Yesterday's Close                               │
└─────────────────────────────────────────────────────┘

MA is a ZONE, Not a Line

Template:Quote

<syntaxhighlight lang="python">

  1. File: signal_generation_trade_management.py:68

ma_buffer_points: float = 25.0 # 21 MA zone width (not a thin line) </syntaxhighlight>

Fab Four Tightness = Explosive Potential

When the Fab Four elements are tight together:

  • Indicates compressed energy
  • Expect powerful move (up or down)
  • Best trades come from narrowness

2.2 Entry Position Hierarchy

Best Entry Positions

FOR SHORTS:
┌─────────────────────────────────────────────────────┐
│  CEILING (Best short position)                      │
│  ═══════════════════════════════════════════        │  ← Price right under Fab Four
│  Price opens HERE                                   │
└─────────────────────────────────────────────────────┘

FOR LONGS:
┌─────────────────────────────────────────────────────┐
│  Price opens HERE                                   │
│  ═══════════════════════════════════════════        │  ← Price right above Fab Four
│  FLOOR (Best long position)                         │
└─────────────────────────────────────────────────────┘

Multi-Timeframe Alignment

Check all timeframes simultaneously:

┌────────┬────────┬────────┬────────┐
│  2min  │  5min  │  15min │  Daily │
│  ────  │  ────  │  ────  │  ────  │
│ Under  │ Under  │ Under  │ Under  │
│  200   │  200   │  200   │  200   │
│ Tight  │ Tight  │ Tight  │ Tight  │
└────────┴────────┴────────┴────────┘
         = ALIGNED = HIGH QUALITY SETUP

Code Implementation

<syntaxhighlight lang="python">

  1. File: setup_quality_detection.py:43-48

timeframe_alignment_weight: float = 0.30 # 30% of setup quality score </syntaxhighlight>


2.3 Bar-by-Bar vs Big Bar Stops

The Rule

When to Use Stop Method Why
Near MA (hugging) Big Bar stops Eliminates noise
Far from MA (extended) Bar-by-bar stops Protect extended gains

The Warning

Template:Quote

Use bar-by-bar ONLY when:

  • Price has moved significantly away from MA
  • "You had better be moving to Pluto"
  • Slant on both 2min and 5min is sharp

Part 3: Stop Loss Methodology

3.1 Stop Placement Hierarchy

Two Stop Options

Type Description When to Use
Event Stop Based on price action event Primary choice
Maximum Stop Dollar-based max loss Fallback when event too far

The Goal

┌─────────────────────────────────────────────────────┐
│  FAB FOUR ZONE (Helping Zone)                       │
├─────────────────────────────────────────────────────┤
│  ↑ STOP SHOULD BE HERE (above/below Fab Four)       │
├─────────────────────────────────────────────────────┤
│  Entry price                                        │
└─────────────────────────────────────────────────────┘

Template:Quote

Code Implementation

<syntaxhighlight lang="python">

  1. File: signal_generation_trade_management.py:59-60

min_stop_distance: float = 40.0 # TICKET-13: Increased from 20 default_stop_distance: float = 40.0 # Minimum buffer for price noise </syntaxhighlight>


3.2 Stop and Reverse Rules

Three criteria for a valid Stop and Reverse:

Criteria Description
1. Immediate Stop out happens INSTANTLY, not gradually
2. Violent Move that stops you is hard, powerful, shakes earth
3. Decent Position New position is NOT into resistance/support

Invalid Stop and Reverse

❌ Going LONG right INTO the 200 MA
❌ Going LONG right INTO tight Fab Four zone
❌ Going SHORT right INTO strong support

Even if immediate + violent, bad position = no reversal

Code Implementation

<syntaxhighlight lang="python">

  1. File: signal_generation_trade_management.py:80-81

bos_structure_lookback: int = 10 # TICKET-11: Extended for BOS stops bos_stop_buffer_points: float = 5.0 # Buffer for structure-based stops </syntaxhighlight>


Part 4: Color Change Confirmation

4.1 The Color Change Entry

Entry Trigger

FOR SHORTS:
Red bar closes BELOW green bar's low → ENTER SHORT
Stop: Above the high

FOR LONGS:
Green bar closes ABOVE red bar's high → ENTER LONG
Stop: Below the low

Key Rule: Don't Wait for Bar to Complete

Template:Quote


4.2 Profit Taking Rules

The Two-Bar Rule

Template:Quote

SHORT TRADE:
┌─────────────────────────────────────────────────────┐
│  GREEN bar (opposite color)                         │
├─────────────────────────────────────────────────────┤
│  RED bar 1 ← IGNITING bar (DO NOT take profit)      │
├─────────────────────────────────────────────────────┤
│  RED bar 2 ← FOLLOW-THROUGH bar (TAKE PROFIT)       │
└─────────────────────────────────────────────────────┘

Position Management Flow

Step 1: Enter with 2 lots
Step 2: Set stop above high
Step 3: Take profit on 1 lot (first follow-through bar)
Step 4: Move stop to break-even
Step 5: Take profit on remaining lot (second follow-through)
Step 6: Done

Template:Quote

Code Implementation

<syntaxhighlight lang="python">

  1. File: signal_generation_trade_management.py:111-118

enable_color_change_filter: bool = False # DISABLED - too restrictive color_change_ma_proximity: float = 20.0 # Points to consider "near" MA require_ma_bounce: bool = False # Don't require strict MA bounce </syntaxhighlight>


4.3 The Traffic Jam Concept

When price gaps below everything from prior day:

┌─────────────────────────────────────────────────────┐
│  Yesterday's 200 MA                                 │
│  Yesterday's 20 MA                                  │
│  Yesterday's Close                                  │
│  ═══════════════════════════════════════════        │
│  TRAFFIC JAM ZONE (resistance on any rally)         │
│  ═══════════════════════════════════════════        │
│                                                     │
│  TODAY'S GAP DOWN OPEN                              │
└─────────────────────────────────────────────────────┘

Rule: Any move UP into the traffic jam meets resistance. Short rallies into this zone.


Part 5: Trading Glossary for Engineers

Trading Term System Translation Code Location Why It Matters
Creeper Move Small-bodied bars, consistent direction, low volume market_state_analysis.py:is_creeper_move Institutional accumulation before explosion. PENALTY: -50 points
Railroad Trend Alternating green/red bars touching MA market_state_analysis.py:is_railroad_trend Healthy trend, not overextended. BONUS: +15 points
Two-Day Trend Price consistently above/below MA for 2+ days market_state_analysis.py:has_two_day_trend Confirms trend maturity. Required for A+ grade
Institutional Fight High volume with narrow range market_state_analysis.py:institutional_fight_in_progress Buyers vs sellers battle. MULTIPLIER: 0.7x score
Discount Zone Price below 21 MA (for longs) probability_zone_analysis.py 80% continuation probability
Premium Zone Price above 21 MA (for shorts) probability_zone_analysis.py Entry zone for short trades
Fab Four PDHL, 21 MA, 200 MA, Yesterday's Close signal_generation.py:_calculate_stop_loss() Stop loss placement hierarchy
Color Change Bar closes opposite color after move probability_zone_analysis.py:ColorChangeDetector Confirms reversal/continuation
Break of Structure (BOS) Price closes beyond recent swing H/L market_state_analysis.py:bos_detected Confirms trend continuation/reversal
MA Zone MA is a band, not thin line (21 MA +/- 25pts) signal_generation.py:ma_buffer_points=25 "Fab Four" concept from philosophy
Trend Phase EARLY / MIDDLE / LATE classification market_state_analysis.py:trend_phase MIDDLE phase = optimal entry timing
Crash Bar Bar > 2x average size, violent probability_zone_analysis.py:crash_bar_multiplier Structural break indicator
Traffic Jam Yesterday's price activity zone Conceptual Resistance zone for gaps
Three-Finger Spread Large gap between Price, 21 MA, 200 MA signal_generation.py:three_finger_spread_threshold Market top indicator

Part 6: Component Architecture

6.1 Pipeline Flow

┌─────────────────┐   ┌───────────────────┐   ┌────────────────────┐
│  Data Manager   │ → │  Trend Analysis   │ → │  Market State      │
│  (1M/5M/1H/1D)  │   │  (MA21, MA200)    │   │  (7 Detections)    │
└─────────────────┘   └───────────────────┘   └────────────────────┘
                                                       ↓
┌─────────────────┐   ┌───────────────────┐   ┌────────────────────┐
│  Trade Exec     │ ← │  Signal Gen       │ ← │  Setup Quality     │
│  (P&L, Costs)   │   │  (Entry/Exit)     │   │  (5-Factor Score)  │
└─────────────────┘   └───────────────────┘   └────────────────────┘

6.2 Setup Quality Detection

File: src/components/setup_quality_detection.py

5-Factor Weighted Scoring System

Factor Weight What It Measures
Timeframe Alignment 30% All timeframes agree on direction
Trend Strength 20% Healthy trend without warnings
Entry Quality 15% Entry near MA, clean execution
Key Level Proximity 20% Entry near support/resistance
Risk/Reward 15% Favorable profit potential

Penalty System

Condition Penalty Trading Reason
Creeper Move -50 pts Quiet accumulation = reversal coming
MA Struggle -30 pts Price can't break MA = weak trend
No Two-Day Trend -30 pts Trend not confirmed
Wrong Trend Phase -25 pts Too early or too late in trend
Not Near MA -40 pts Entry too far from edge
Institutional Fight 0.7x Wait for resolution

Grade Thresholds

Grade Score Position Size Auto-Trade?
A+ >= 90 2 lots Yes
A >= 80 1 lot Yes
B >= 70 1 lot No
C >= 60 1 lot No
D >= 50 1 lot No
F < 50 1 lot No

6.3 Market State Analysis

File: src/components/market_state_analysis.py

7 Detection Algorithms

# Algorithm What It Detects Trading Implication
1 Railroad Trend Healthy alternating bars +15 bonus, trend continuation likely
2 Creeper Move Small bars, consistent direction -50 penalty, reversal imminent
3 Volatility Calc ATR-based regime Adjust stop distance
4 Market State TRENDING / SIDEWAYS / VOLATILE Different strategy rules
5 Two-Day Trend Multi-day momentum Required for A+ grade
6 Trend Phase EARLY / MIDDLE / LATE MIDDLE = optimal entry
7 Institutional Behavior Volume + price patterns Fight = wait, Accumulation = prepare

6.4 Signal Generation

File: src/components/signal_generation_trade_management.py

Entry Filters Applied

Filter Config Key Purpose
Hour Filter blocked_hours: [9, 22, 23] Block loss-making hours
MA Direction enable_ma_direction_filter: True LONG only if MA rising
Probability Zone enable_probability_zone_filter: True Entry in favorable zones
Color Change enable_color_change_filter: False Disabled (too restrictive)

Part 7: Branch Changes (service/backtest → rikk_mtf_backtest001)

7.1 Complete Git Diff Summary

Total Changes: 65 files changed across core source, scripts, and data

Modified (M) Source Files

File Type Key Changes
signal_generation_trade_management.py Component TICKET-7,8,10,11,12,13,18,19,20,21,24 + PDF fixes + Grading fix
trade_execution_engine.py Component TICKET-9,13,15,17,20: Trailing stop, breakeven, ATR
market_state_analysis.py Component TICKET-25: 5MIN → 1HOUR data
setup_quality_detection.py Component TICKET-5: Position sizing fix
timeframe_conversion.py Core Date column fix, 1m skip, emoji removal
data_structures.py Core TICKET-15: current_stop_price field
multi_timeframe_analysis.py Component Whitespace cleanup
main.py Entry TICKET-12 config, emoji removal

Added (A) Files

File Purpose
probability_zone_analysis.py NEW: Implements trade_philosophy.pdf (974 lines)
50+ scripts/analyze_*.py Analysis scripts for hypothesis building

7.2 JIRA Ticket Fixes (Complete Details)

TICKET-5: Position Sizing Fix

File: setup_quality_detection.py:544-567

Problem: Previous sizing = 100-200 lots = Rs 5.7 Crore exposure on Rs 1 lakh capital (5700x!)

<syntaxhighlight lang="python">

  1. BEFORE (service/backtest):

multipliers = {

   SetupQualityGrade.A_PLUS: 200,  # 200 lots (impossible!)
   SetupQualityGrade.A: 150,
   SetupQualityGrade.B: 100,
   # ...

}

  1. AFTER (rikk_mtf_backtest001):

position_sizes = {

   SetupQualityGrade.A_PLUS: 2,    # 2 lots (Rs 1.14L exposure - realistic)
   SetupQualityGrade.A: 1,         # 1 lot
   SetupQualityGrade.B: 1,
   SetupQualityGrade.C: 1,
   SetupQualityGrade.D: 1,
   SetupQualityGrade.F: 1

} </syntaxhighlight>


TICKET-7: R:R Preservation After Slippage

File: signal_generation_trade_management.py:241-285

Problem: Slippage moved entry but stop/target stayed fixed = corrupted R:R ratio

<syntaxhighlight lang="python">

  1. BEFORE: Stop and target not adjusted after slippage

actual_execution_price = execution_price + market_slippage # Entry moved

  1. BUT stop_loss_price and take_profit_price stayed at original levels!
  2. RESULT: R:R became inverted (target closer than stop)
  1. AFTER: Shift stop and target with entry to maintain R:R
  2. Example (LONG with +1.5 pts slippage):
  3. Before: entry=5710, stop=5680, target=5740 (30 pts each, 1:1 R:R)
  4. After slippage: entry=5711.5, stop=5680, target=5740
  5. WRONG R:R: stop=31.5 pts, target=28.5 pts (INVERTED!)
  6. FIX: entry=5711.5, stop=5681.5, target=5741.5 (30 pts each, 1:1 R:R)

if signal.direction == Direction.LONG:

   actual_execution_price = execution_price + market_slippage
   # TICKET-7: Shift stop and target UP by slippage to maintain R:R
   adjusted_stop_loss = signal.stop_loss_price + market_slippage
   adjusted_take_profit = signal.take_profit_price + market_slippage

else: # SHORT

   actual_execution_price = execution_price - market_slippage
   # TICKET-7: Shift stop and target DOWN by slippage to maintain R:R
   adjusted_stop_loss = signal.stop_loss_price - market_slippage
   adjusted_take_profit = signal.take_profit_price - market_slippage

</syntaxhighlight>


TICKET-8: CTT Rate Fix

File: signal_generation_trade_management.py:48-55

Problem: CTT was 0.05% (5x too high!). Dhan broker calculates Rs 52 on Rs 5.2L = 0.01%

<syntaxhighlight lang="python">

  1. BEFORE:

transaction_tax_rate: float = 0.000500 # 0.05% - WRONG!

  1. AFTER:
  2. MCX CTT = 0.01% on SELL side only. Since code charges at entry+exit,
  3. use 0.005% per leg so round-trip = 0.01% total (matches actual CTT)
  4. Dhan verified: CTT Rs 52 on Rs 5,20,000 sell value = 0.01%

transaction_tax_rate: float = 0.000050 # 0.005% per leg × 2 = 0.01% total </syntaxhighlight>


TICKET-9: Market Impact Slippage Cap

File: trade_execution_engine.py:40-42, 585-605

Problem: 100 lots × 0.1 = 10 pts slippage (excessive!)

<syntaxhighlight lang="python">

  1. BEFORE: No cap on market impact

size_impact = signal.position_size * self.config.market_impact_factor

  1. AFTER: Cap to prevent excessive slippage

max_market_impact_slippage: float = 2.0 # Maximum 2 points

raw_size_impact = signal.position_size * self.config.market_impact_factor size_impact = min(raw_size_impact, self.config.max_market_impact_slippage)

  1. For 1-2 lots (after TICKET-5 fix):
  2. - base: 1.0 pts
  3. - market_impact: min(1×0.1, 2.0) = 0.1 pts (capped at 2.0)
  4. - volatility: 0.5 pts
  5. - total: ~1.6 pts (realistic for MCX crude)

</syntaxhighlight>


TICKET-10: Entry Technique Alignment

File: signal_generation_trade_management.py:2012-2140

Problem: Entry technique logic didn't match strategy_engine.py priority order

<syntaxhighlight lang="python">

  1. COMPLETE REWRITE of _determine_entry_technique():
  2. BEFORE: Random priority order, creeper before BOS, missing key level checks
  1. AFTER (aligned with strategy_engine.py::_classify_entry_technique_exact()):
  2. PRIORITY 1: Creeper move → NEAR_MA (NOT green_bar/red_bar!)
  3. PRIORITY 2: BOS detected → BOS_ENTRY (only if NOT creeper)
  4. PRIORITY 3: Near key level → DISCOUNT_ZONE / BREAKOUT_PULLBACK
  5. PRIORITY 4: Near MA → MA_BOUNCE
  6. PRIORITY 5: Two-day trend → TWO_GREEN_DAILY / TWO_RED_DAILY
  7. PRIORITY 6: Railroad trend → GREEN_BAR_AFTER_PULLBACK / RED_BAR_AFTER_RALLY
  8. PRIORITY 7: Fallback → NEAR_MA

</syntaxhighlight>


TICKET-11: BOS Stop Settings

File: signal_generation_trade_management.py:78-81

Problem: 5-bar lookback + no buffer = stop too close in trending markets = 66.7% stop rate

<syntaxhighlight lang="python">

  1. BEFORE:

structure_lookback: int = 5 # Too short for BOS

  1. AFTER:

bos_structure_lookback: int = 10 # Extended lookback for BOS stops bos_stop_buffer_points: float = 5.0 # Buffer below/above structure </syntaxhighlight>


TICKET-12: Hour Filter

File: signal_generation_trade_management.py:83-93, 126-137, 571-581

Problem: Certain hours consistently lose money

<syntaxhighlight lang="python">

  1. NEW CONFIGURATION:

enable_hour_filter: bool = True blocked_hours: [9, 22, 23] # Block 9-10 AM and after 10 PM

  1. Data-driven analysis showed (from 1439 trades):
  2. Worst hours: 15(-Rs244K), 22(-Rs209K), 09(-Rs199K), 21(-Rs101K), etc.
  3. Profitable hours: 16, 17, 18, 19, 23 (total +Rs341K)
  1. Applied in generate_signal():

if self.config.enable_hour_filter and self.config.blocked_hours:

   current_hour = current_timestamp.hour
   if current_hour in self.config.blocked_hours:
       return None  # No signal during blocked hours

</syntaxhighlight>


TICKET-13: Minimum Stop Distance

File: signal_generation_trade_management.py:57-60, 852-870

Problem: 20pt stops hit too frequently due to normal price noise

<syntaxhighlight lang="python">

  1. BEFORE:

default_stop_distance: float = 20.000000

  1. AFTER:

min_stop_distance: float = 40.000000 # Minimum stop distance default_stop_distance: float = 40.000000 # Default increased

  1. ENFORCEMENT in generate_signal():
  2. TICKET-13 FIX: ENFORCE MINIMUM STOP DISTANCE (40 POINTS)

stop_distance = max(calculated_stop_distance, self.config.min_stop_distance) </syntaxhighlight>


TICKET-15: Trailing Stop Tracking

File: data_structures.py:2982-2984, trade_execution_engine.py:54-70, 295-392

Problem: No way to track current trailing stop position vs original

<syntaxhighlight lang="python">

  1. NEW FIELD in Trade dataclass:

current_stop_price: Optional[float] = None # Current trailing stop (moves with price)

  1. NEW METHOD in TradeExecutionEngine:

def _update_trailing_stop(self, trade: Trade, current_high: float, current_low: float):

   """
   TICKET-15/17/20: Update stop based on price movement.
   Two-Phase Stop Management:
   PHASE 1 - Breakeven (TICKET-17): Move stop to entry when profitable
   PHASE 2 - Trailing (TICKET-15/20): Trail stop behind price
   """
   if trade.current_stop_price is None:
       trade.current_stop_price = trade.original_stop_price
   # Calculate trailing distance (ATR-based or fixed)
   if self.config.trailing_stop_method == "ATR_MULTIPLE":
       trailing_distance = self.current_atr * self.config.atr_multiplier
       trailing_distance = max(trailing_distance, 15.0)  # Min 15 pts for Crude
   else:
       trailing_distance = self.config.trailing_stop_distance
   if trade.direction == Direction.LONG:
       current_profit = current_high - trade.entry_price
       if current_profit >= self.config.trailing_stop_activation:
           new_stop = current_high - trailing_distance
           if new_stop > trade.current_stop_price:
               trade.current_stop_price = new_stop  # Only move UP

</syntaxhighlight>


TICKET-17: Breakeven Stop

File: trade_execution_engine.py:64-68

Problem: Needed automatic breakeven move when in profit

<syntaxhighlight lang="python">

  1. NEW CONFIGURATION:

enable_breakeven_stop: bool = True breakeven_activation: float = 25.0 # Points profit before moving to breakeven breakeven_buffer: float = 2.0 # Points above/below entry for buffer

  1. Tested 10pt activation but cut winners too short (26% WR vs 49%)
  2. 25pt activation is the sweet spot

</syntaxhighlight>


TICKET-18: Creeper Move Handling

File: signal_generation_trade_management.py:582-595

Problem: Previous implementation blocked creeper signals entirely (too aggressive)

<syntaxhighlight lang="python">

  1. BEFORE: Creeper signals blocked with return None
  1. AFTER (comment explains fix):
  2. CORE BEHAVIOR: Creeper moves get -50 penalty + 0.7x target + uses NEAR_MA
  3. Previous implementation: Blocked entirely with return None (too aggressive)
  4. FIX: Let creeper signals through - penalty applied in setup_quality_detection,
  5. NEAR_MA technique used in _determine_entry_technique()
  6. Let the scoring system decide rather than blocking outright

</syntaxhighlight>


TICKET-19: MA Direction Filter + Score Adjustment

File: signal_generation_trade_management.py:95-97, 987-1034, 1955-2010

Problem: Trades against MA21 slope direction had poor performance

<syntaxhighlight lang="python">

  1. CONFIGURATION:

enable_ma_direction_filter: bool = True

  1. DIRECTION LOGIC COMPLETE REWRITE (_determine_signal_direction):
  2. BEFORE: Used alignment score threshold (>= 60%)
  3. AFTER: Uses MA21 slope as primary direction source

def _determine_signal_direction(self, timeframe_analysis, market_state, market_data=None):

   """MA21 SLOPE ALIGNMENT DIRECTION LOGIC (trade_philosophy.pdf)"""
   trend_direction = getattr(market_state, 'trend_direction', None)
   if trend_direction == "up":
       return Direction.LONG      # MA21 rising → only LONG
   elif trend_direction == "down":
       return Direction.SHORT     # MA21 declining → only SHORT
   else:
       # Fallback to MTF primary_direction if MA21 is flat/unknown
       return getattr(timeframe_analysis, 'primary_direction', None)
  1. SCORE ADJUSTMENT (lines 987-1034):
  2. +15% bonus if trade direction aligns with MA21 slope
  3. -10% penalty if trade direction against MA21 slope

</syntaxhighlight>


TICKET-20: Probability Zone Filter + ATR Trailing

File: signal_generation_trade_management.py:99-109, 628-817, trade_execution_engine.py:57-63, 295-340

Problem: Needed trade_philosophy.pdf concepts in code

<syntaxhighlight lang="python">

  1. NEW CONFIGURATION (Probability Zones):

enable_probability_zone_filter: bool = True probability_zone_swing_lookback: int = 20 probability_zone_min_range: float = 20.0 three_finger_spread_threshold: float = 0.02 crash_bar_multiplier: float = 2.0 sideways_mean_reversion: bool = True

  1. NEW CONFIGURATION (ATR Trailing):

trailing_stop_method: str = "ATR_MULTIPLE" # or "FIXED_POINTS" atr_period: int = 14 atr_multiplier: float = 2.0 # 2x ATR = trailing distance

  1. NEW ATR CALCULATION in trade_execution_engine.py:295-340

def _calculate_atr(self, five_min_data: Dict) -> None:

   """Calculate Average True Range for dynamic trailing stop."""
   # TrueRange = max(high-low, abs(high-prev_close), abs(low-prev_close))
   # ATR = SMA(TrueRange, period)
   true_ranges = []
   for i in range(1, len(high_vals)):
       tr = max(
           high_vals[i] - low_vals[i],           # Current high - low
           abs(high_vals[i] - close_vals[i-1]),  # High - previous close
           abs(low_vals[i] - close_vals[i-1])    # Low - previous close
       )
       true_ranges.append(tr)
   self.current_atr = sum(true_ranges) / len(true_ranges)

</syntaxhighlight>


TICKET-21: Color Change Filter (DISABLED)

File: signal_generation_trade_management.py:111-118

Problem: color_change.pdf patterns too restrictive for automation

<syntaxhighlight lang="python">

  1. CONFIGURATION (disabled):

enable_color_change_filter: bool = False # DISABLED - too restrictive color_change_ma_proximity: float = 20.0 # Points to consider "near" MA require_ma_bounce: bool = False # Too strict color_change_require_in_zones: bool = True

  1. NOTE: ColorChangeDetector class still exists for future use
  2. Implements liquidity sweep patterns:
  3. - LONG: Green bar sweeps BELOW red bar low + bounce from 21 MA
  4. - SHORT: Red bar sweeps ABOVE green bar high + rejection from 21 MA

</syntaxhighlight>


TICKET-24: Creeper Move Entry Technique Fix

File: signal_generation_trade_management.py:2037-2050

Problem: strategy_engine.py bug - uses wrong entry technique for creeper moves

<syntaxhighlight lang="python">

  1. STRATEGY ENGINE BUG FOUND:
  2. backtesting_standalone/src/strategy_engine.py lines 3338-3380
  3. checks bos_detected FIRST but doesn't consider is_creeper_move.
  4. This causes BOS entries in creeper moves (inappropriate).
  1. FIX: Check creeper FIRST before BOS

if is_creeper:

   # Creeper gets -50 penalty + 0.7x target from setup_quality_detection
   # But uses NEAR_MA as technique (NOT green_bar/red_bar!)
   return EntryTechnique.NEAR_MA  # Strategy engine fallback

</syntaxhighlight>


TICKET-25: Market State 5MIN → 1HOUR

File: market_state_analysis.py:191-360

Problem: Creeper threshold 0.5% calibrated for 1H bars (~0.8-1.2% range), but code used 5MIN (~0.16% range) = 98.9% false positives!

<syntaxhighlight lang="python">

  1. BEFORE:

required_tf = TimeframeValue.FIVE_MIN

  1. AFTER:

def validate_input(self, input_data: Dict, context: ComponentContext):

   """
   TICKET-25 FIX: Market state analysis uses 1-HOUR data (not 5MIN)
   to match strategy_engine.py behavior for creeper/railroad detection.
   """
   primary_tf = TimeframeValue.ONE_HOUR
   fallback_tf = TimeframeValue.FIVE_MIN
   if primary_tf in input_data and input_data[primary_tf] is not None:
       required_tf = primary_tf
   elif fallback_tf in input_data and input_data[fallback_tf] is not None:
       required_tf = fallback_tf
       # Warning: 5MIN fallback may cause inaccurate creeper detection

def _get_primary_timeframe(self, input_data: Dict) -> TimeframeValue:

   """
   TICKET-25 FIX: Use ONE_HOUR for market state analysis.
   The 0.5% creeper threshold is calibrated for 1-HOUR bars (~0.8-1.2% typical range),
   not 5-MIN bars (~0.16% typical range). Using 5MIN caused 98.9% false positives.
   """
   primary_tf = TimeframeValue.ONE_HOUR  # Was FIVE_MIN

</syntaxhighlight>


PDF-FIX: MA Buffer Points

File: signal_generation_trade_management.py:67-68

Source: Fab Four concept - "MA is a zone, not a thin line"

<syntaxhighlight lang="python">

  1. BEFORE:

ma_buffer_points: float = 5.000000 # Too tight!

  1. AFTER:
  2. PDF-FIX: MA is a "zone, not a thin line" (Fab Four) - use wider buffer

ma_buffer_points: float = 25.000000 # 21 MA zone width </syntaxhighlight>


GRADING FIX: Score-to-Grade Recalculation

File: signal_generation_trade_management.py:1054, 1132-1170

Problem: Grade assigned from capped original score instead of adjusted score

<syntaxhighlight lang="python">

  1. BEFORE:

setup_quality=setup_quality.grade, # Grade from CAPPED original score (79) setup_score=setup_quality.score, # Original score (79)

  1. Problem: Score=79 → Grade=A, but if adjustment makes it 89, should be A+!
  1. AFTER:

setup_quality=self._calculate_grade_from_score(adjusted_score), # RECALCULATED setup_score=adjusted_score, # MA-adjusted score

  1. NEW METHOD ADDED:

def _calculate_grade_from_score(self, score: float) -> SetupQualityGrade:

   """GRADING FIX: Calculate grade from FINAL adjusted score."""
   if score >= 90: return SetupQualityGrade.A_PLUS
   elif score >= 80: return SetupQualityGrade.A
   elif score >= 70: return SetupQualityGrade.B
   elif score >= 60: return SetupQualityGrade.C
   elif score >= 50: return SetupQualityGrade.D
   else: return SetupQualityGrade.F

</syntaxhighlight>


7.3 New File: probability_zone_analysis.py (974 lines)

This file implements concepts from trade_philosophy.pdf:

Enums Defined

<syntaxhighlight lang="python"> class ProbabilityZone(Enum):

   TOP_THIRD = "top_third"           # 80% continuation probability
   TOP_HALF = "top_half"             # 65% continuation probability
   BOTTOM_HALF = "bottom_half"       # 35% continuation probability
   BOTTOM_THIRD = "bottom_third"     # 15% continuation (85% reversal)

class MarketStructure(Enum):

   UPTREND = "uptrend"               # Price > 21 MA > 200 MA
   DOWNTREND = "downtrend"           # Price < 21 MA < 200 MA
   SIDEWAYS = "sideways"             # No clear structure
   THREE_FINGER_SPREAD_BULL = "..."  # Large spread (bearish signal)
   THREE_FINGER_SPREAD_BEAR = "..."  # Large spread (bullish signal)

class PullbackType(Enum):

   HEALTHY_PULLBACK = "healthy_pullback"  # 45-degree drift, holds above halfway
   COLLAPSE = "collapse"                   # Vertical drop, breaks deeply
   NO_PULLBACK = "no_pullback"            # Price at or near highs
   BOUNCE = "bounce"                       # Bounce after crash (short opportunity)

class ColorChangeType(Enum):

   BULLISH_REVERSAL = "bullish_reversal"  # Green bar takes out red bar high
   BEARISH_REVERSAL = "bearish_reversal"  # Red bar takes out green bar low
   NO_PATTERN = "no_pattern"

</syntaxhighlight>

Key Classes

  • ProbabilityZoneResult - Analysis result with zone, probabilities, MA structure
  • ColorChangeResult - Pattern detection result
  • ProbabilityZoneConfig - Configuration with thresholds
  • ProbabilityZoneAnalyzer - Main analyzer class
  • ColorChangeDetector - Detects liquidity sweep patterns

Configuration Defaults

<syntaxhighlight lang="python"> @dataclass class ProbabilityZoneConfig:

   top_third_probability: float = 0.80    # 80% continuation
   top_half_probability: float = 0.65     # 65% continuation
   bottom_half_probability: float = 0.35  # 35% continuation
   bottom_third_probability: float = 0.15 # 15% continuation
   swing_lookback_bars: int = 20          # Bars for swing H/L
   crash_bar_multiplier: float = 2.0      # Bar > 2x avg = crash
   three_finger_min_spread_pct: float = 0.02  # 2% spread threshold

</syntaxhighlight>


7.4 timeframe_conversion.py Changes

File: src/core/timeframe_conversion.py

Changes

  1. Emoji removal - All emoji characters replaced with [OK], [FAIL], [CONV], etc.
  2. Date column fix - Handle 'date' as alias for 'timestamp'
  3. 1m skip - Don't overwrite source file when saving
  4. Mixed timestamp format - Use format='mixed' for pandas parsing

<syntaxhighlight lang="python">

  1. Date column alias:

if 'date' in source_df.columns and 'timestamp' not in source_df.columns:

   source_df = source_df.rename(columns={'date': 'timestamp'})
   logger.info("[FIX] Renamed 'date' column to 'timestamp'")
  1. Skip 1m overwrite:

if timeframe == '1m':

   logger.info(f"[SKIP] 1m: Source file preserved (not overwritten)")
   continue
  1. Mixed timestamp parsing:

pd.to_datetime(df['timestamp'], format='mixed') </syntaxhighlight>


7.5 main.py Changes

File: src/main.py

Changes

  1. Hour filter configuration - TICKET-12 support
  2. Emoji removal - Console output cleanup

<syntaxhighlight lang="python">

  1. TICKET-12: Hour Filter configuration:

enable_hour_filter=strategy_config.get('enable_hour_filter', False), blocked_hours=strategy_config.get('blocked_hours', [])

print(f" TICKET-12 Hour Filter: Enabled={signal_generator_config.enable_hour_filter}, "

     f"Blocked Hours={signal_generator_config.blocked_hours}")

</syntaxhighlight>


7.6 Complete File Tree

services/backtest/src/
├── components/
│   ├── market_state_analysis.py      # TICKET-25: 5MIN → 1HOUR
│   ├── multi_timeframe_analysis.py   # Whitespace cleanup
│   ├── probability_zone_analysis.py  # NEW: trade_philosophy.pdf (974 lines)
│   ├── setup_quality_detection.py    # TICKET-5: position sizing
│   ├── signal_generation_trade_management.py  # TICKET-7,8,10,11,12,13,18,19,20,21,24 + GRADING FIX
│   └── trade_execution_engine.py     # TICKET-9,13,15,17,20: trailing/breakeven/ATR
├── core/
│   ├── data_structures.py            # TICKET-15: current_stop_price field
│   └── timeframe_conversion.py       # Date fix, 1m skip, emoji removal
└── main.py                           # TICKET-12 config, emoji removal

services/backtest/scripts/           # 50+ NEW analysis scripts
├── analyze_alignment_pnl.py
├── analyze_alignment_pnl_v2.py
├── analyze_aplus.py
├── analyze_by_hour.py
├── analyze_combined_filters.py
├── analyze_crash_short_potential.py
├── analyze_hour_filter.py
├── analyze_hourly_pnl.py
├── analyze_long_short_detail.py
├── analyze_longs.py
├── analyze_ma_alignment.py
├── analyze_ma_slope_filter.py
├── analyze_morning_times.py
├── analyze_pdf_results.py
├── analyze_quick_exits.py
├── analyze_red_bar_rally.py
├── analyze_shorts.py
├── analyze_stop_exits.py
├── analyze_stop_loss_detail.py
├── analyze_test_summary.py
├── analyze_trade_bias.py
├── analyze_trading_hours_filter.py
├── analyze_trend_direction_at_entry.py
├── aplus_vs_a_analysis.py
├── check_all_data.py
├── check_costs.py
├── check_data_range.py
├── check_price_trend.py
├── comprehensive_analysis.py
├── comprehensive_backtest_analysis.py
├── comprehensive_summary.py
├── cost_impact_analysis.py
├── detailed_monthly.py
├── diagnose_color_change.py
├── diagnose_direction_bias.py
├── framework_comparison_analysis.py
├── generate_test_summary.py
├── grade_and_equity.py
├── monthly_breakdown.py
├── no_morning_analysis.py
├── path_to_profitability.py
├── philosophy_v1_blend_analysis.py
├── root_cause_summary.py
├── short_market_state_alignment.py
├── short_technique_analysis.py
├── simulate_target_rr.py
├── simulate_target_rr_v2.py
├── stop_out_deep_analysis.py
├── strategy_engine_gap_analysis.py
├── test_summary.py
└── v1_optimization_impact_analysis.py

Part 8: Strategy Configuration

8.1 76D Parameter Vector

The strategy uses regime-aware configuration with 76 parameters:

  • 44 Global Parameters - Constant across all market regimes
  • 32 Regime Parameters - 8 parameters × 4 market regimes

File: src/config/strategy_config.py

Key Parameters

Parameter Default Description
primary_ma_period 21 Main trend MA
secondary_ma_period 200 Long-term trend MA
default_stop_distance 40 pts Minimum stop distance
default_risk_reward 2.0 Target R:R ratio
ma_buffer_points 25 pts MA zone width
creeper_move_penalty -50 Score reduction
railroad_trend_bonus +15 Score increase

Part 9: Decision Trees

9.1 Should I Trade This Setup?

START: Signal Generated
   │
   ▼
[Is hour blocked (9, 22, 23)?]
   │ Yes → SKIP (loss-making hours)
   │ No ↓
   ▼
[Is MA21 direction aligned with trade?]
   │ LONG + MA rising? → Continue
   │ SHORT + MA falling? → Continue
   │ No alignment → SKIP
   │
   ▼
[Is price in probability zone?]
   │ LONG + Bottom Third? → Continue (80% odds)
   │ SHORT + Top Third? → Continue (80% odds)
   │ Wrong zone → SKIP
   │
   ▼
[Calculate Setup Quality Score]
   │
   ├─ Apply 5-factor scoring (TF 30%, Trend 20%, Entry 15%, KeyLevel 20%, R:R 15%)
   ├─ Apply penalties (creeper -50, MA struggle -30, etc.)
   ├─ Apply institutional fight multiplier (0.7x)
   ├─ Apply MA direction adjustment (+15% aligned, -10% against)
   │
   ▼
[Recalculate Grade from ADJUSTED score]
   │
   ├─ A+ or A → Auto-trade eligible (2 lots for A+, 1 lot for A)
   ├─ B to D → Manual review (1 lot)
   ├─ F → Skip or minimal size
   │
   ▼
[Execute Trade with Position Size]

9.2 Where to Place Stop?

START: Trade Direction Determined
   │
   ▼
[Is Fab Four zone tight and close?]
   │ Yes → Place stop BEYOND Fab Four zone
   │ No ↓
   ▼
[Can I afford stop beyond Fab Four?]
   │ Yes → Use EVENT stop (beyond Fab Four)
   │ No → Use MAXIMUM loss stop ($6000 max)
   │
   ▼
[ENFORCE minimum 40pt stop (TICKET-13)]
   │
   ▼
[Once trade moves in favor:]
   │
   ├─ 25 pts profit → Move stop to breakeven (TICKET-17)
   ├─ 20+ pts profit → Start trailing (TICKET-15/20)
   ├─ Use ATR-based trail distance (2x ATR, min 15 pts)
   │
   ▼
[Stop Placement Complete]

Part 10: Code Review Guidelines

10.1 What Reviewers Should Check

  • Code correctness (syntax, bugs)
  • Integration (doesn't break other components)
  • Test coverage
  • Precision (6-decimal places per spec)
  • Performance (no excessive logging)

10.2 What Reviewers Should NOT Question

  • The penalty values themselves (-50, -30, etc.)
  • Why 21 MA and not 20 MA
  • Why specific thresholds (these are trading decisions)
  • Why certain hours are blocked

10.3 Trading Authority Principle

Rikk has final authority on:

  • Entry/exit conditions
  • Threshold values
  • Setup definitions
  • What constitutes a valid signal
  • Penalty/bonus amounts

Engineers have authority on:

  • Code quality and structure
  • Performance optimization
  • Error handling
  • System integration
  • Test coverage

Part 11: Quick Reference Cards

Card 1: Probability Zones

TOP THIRD    = 80% continuation (SHORT zone)
TOP HALF     = 65% continuation
BOTTOM HALF  = 35% continuation
BOTTOM THIRD = 15% continuation (LONG zone with 85% reversal odds)

Card 2: Setup Quality Formula

Score = (TF_align × 0.30) + (Trend × 0.20) + (Entry × 0.15) + (KeyLevel × 0.20) + (R:R × 0.15)

Then apply:
- Creeper detected? → Score - 50
- MA struggle? → Score - 30
- No two-day trend? → Score - 30
- Wrong phase? → Score - 25
- Institutional fight? → Score × 0.7
- MA direction aligned? → Score + 15%
- MA direction against? → Score - 10%

Finally: Recalculate grade from ADJUSTED score (not original!)

Card 3: Profit Taking

1. Enter with 2 lots
2. Set stop above high (short) / below low (long)
3. Wait for follow-through bar (2nd bar after opposite color)
4. Take profit on 1 lot
5. Move stop to break-even
6. Wait for next follow-through bar
7. Take profit on remaining lot
8. Done

Card 4: JIRA Tickets Summary

Ticket One-Line Summary
TICKET-5 Position sizing: 200 lots → 2/1 lots (realistic for Rs 1L capital)
TICKET-7 R:R preservation: shift stop/target with slippage
TICKET-8 CTT rate: 0.05% → 0.005% per leg (5x fix)
TICKET-9 Market impact: cap slippage at 2 pts max
TICKET-10 Entry technique: align with strategy_engine.py priority order
TICKET-11 BOS stops: 5 → 10 bar lookback + 5pt buffer
TICKET-12 Hour filter: block hours 9, 22, 23 (loss-making)
TICKET-13 Min stop: 20 → 40 pts (noise protection)
TICKET-15 Trailing stop: add current_stop_price tracking
TICKET-17 Breakeven: move stop to entry at 25pt profit
TICKET-18 Creeper handling: let through (don't block), use penalty
TICKET-19 MA direction: use slope as primary direction source
TICKET-20 Probability zones + ATR trailing (trade_philosophy.pdf)
TICKET-21 Color change: disabled (too restrictive)
TICKET-24 Creeper entry: use NEAR_MA technique (not green/red bar)
TICKET-25 Market state: 5MIN → 1HOUR for creeper detection
GRADING FIX Recalculate grade from adjusted score
PDF-FIX MA buffer: 5 → 25 pts (MA is zone, not line)

Last Updated: 2026-01-05 | Branch: rikk_mtf_backtest001 | Validated: 19-month backtest