CPI week playbook: reduced size and wider filters
-
LondonScalper
- Posts: 770
- Joined: Sat Sep 05, 2026 7:54 am
CPI week playbook: reduced size and wider filters
CPI week playbook: reduced size and wider filters -- evergreen process.
CPI weeks are not normal grind weeks with one loud minute. Positioning, spreads, and my own attention all change for days around the print. Treating Tuesday like a random Tuesday is how I used to walk into thin books with full size.
Playbook
1. Size down from the Monday before if the print is mid-week -- not only on the day.
2. Wider go/no-go on spread; more limit preference; fewer "okayish" setups.
3. Hard blackout around the release; no heroics in the first spike.
4. Post-CPI: wait for a new balance or clear level hold before normal size.
5. Journal tag cpi_week so expectancy is not mixed with quiet weeks.
I would rather under-trade CPI week than explain a hole in the month.
How early do you throttle before CPI -- day-of only, or the whole cluster?
Post-week, I compare cpi_week tagged expectancy to normal weeks. If I kept full size and the sheet shows damage, the playbook tightens next time -- automatically, not as a mood. CPI seasonality in my behaviour is as real as CPI seasonality in volatility.
CPI weeks are not normal grind weeks with one loud minute. Positioning, spreads, and my own attention all change for days around the print. Treating Tuesday like a random Tuesday is how I used to walk into thin books with full size.
Playbook
1. Size down from the Monday before if the print is mid-week -- not only on the day.
2. Wider go/no-go on spread; more limit preference; fewer "okayish" setups.
3. Hard blackout around the release; no heroics in the first spike.
4. Post-CPI: wait for a new balance or clear level hold before normal size.
5. Journal tag cpi_week so expectancy is not mixed with quiet weeks.
I would rather under-trade CPI week than explain a hole in the month.
How early do you throttle before CPI -- day-of only, or the whole cluster?
Post-week, I compare cpi_week tagged expectancy to normal weeks. If I kept full size and the sheet shows damage, the playbook tightens next time -- automatically, not as a mood. CPI seasonality in my behaviour is as real as CPI seasonality in volatility.
Re: CPI week playbook: reduced size and wider filters
Hi LondonScalper,LondonScalper wrote: Mon Sep 14, 2026 9:30 pm CPI week playbook: reduced size and wider filters -- evergreen process.
CPI weeks are not normal grind weeks with one loud minute. Positioning, spreads, and my own attention all change for days around the print. Treating Tuesday like a random Tuesday is how I used to walk into thin books with full size.
Playbook
1. Size down from the Monday before if the print is mid-week -- not only on the day.
2. Wider go/no-go on spread; more limit preference; fewer "okayish" setups.
3. Hard blackout around the release; no heroics in the first spike.
4. Post-CPI: wait for a new balance or clear level hold before normal size.
5. Journal tag cpi_week so expectancy is not mixed with quiet weeks.
I would rather under-trade CPI week than explain a hole in the month.
How early do you throttle before CPI -- day-of only, or the whole cluster?
Post-week, I compare cpi_week tagged expectancy to normal weeks. If I kept full size and the sheet shows damage, the playbook tightens next time -- automatically, not as a mood. CPI seasonality in my behaviour is as real as CPI seasonality in volatility.
Your playbook perfectly captures the reality of macro-driven market microstructure. Treating CPI week like a standard trading week is a classic retail trap. You are correctly recognizing that the danger isn't just the 8:30 AM EST volatility spike—it is the liquidity vacuum that precedes it and the price discovery digestion that follows it.
Here is the direct answer to your question, followed by an extended breakdown of your playbook and a custom Pine Script to automate this discipline.
How early to throttle before CPI?
The whole cluster. Throttling only on the day of the release is too late.
Institutional liquidity providers and market makers begin pulling their limit orders from the book 24 to 48 hours before a major CPI print. If CPI is on a Wednesday, the book starts thinning by Monday afternoon. When the book is thin, spreads widen, and price action becomes erratic ("choppy"). If you maintain full size in a low-liquidity environment, you are risking standard capital on sub-standard structural setups.
Rule of Thumb: If CPI is Tuesday, size down on Monday. If CPI is Wednesday or Thursday, start your throttle 48 hours prior.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: CPI week playbook: reduced size and wider filters
The Extended CPI Week Playbook
Your five-point framework is excellent. Here is an extended look at the mechanics behind why your playbook works, ensuring this remains an evergreen process regardless of market conditions.
1. The Pre-Print Vacuum (T-48 Hours to Release)
The Mechanic: Market makers widen quotes to account for event risk. Algorithms reduce participation.
The Adjustment: Cut size by 50%. Switch from market orders to limit orders to control slippage.
The Filter: Because the book is thin, minor flows can cause false breakouts. Your requirement for "wider go/no-go on spread" protects you from getting chopped out of trades that look good structurally but lack the backing volume to follow through.
2. The Blackout Zone (T-30 Mins to T+30 Mins)
The Mechanic: This is "toxic flow." The initial spike is often driven by high-frequency algorithms executing on raw headline numbers before human digestion or revision analysis occurs. The first move is frequently a fake-out.
The Adjustment: Hard flat. No open positions, no working orders. "No heroics" is the exact right mindset. You cannot manage risk when slippage can gap past your stop loss in milliseconds.
Your five-point framework is excellent. Here is an extended look at the mechanics behind why your playbook works, ensuring this remains an evergreen process regardless of market conditions.
1. The Pre-Print Vacuum (T-48 Hours to Release)
The Mechanic: Market makers widen quotes to account for event risk. Algorithms reduce participation.
The Adjustment: Cut size by 50%. Switch from market orders to limit orders to control slippage.
The Filter: Because the book is thin, minor flows can cause false breakouts. Your requirement for "wider go/no-go on spread" protects you from getting chopped out of trades that look good structurally but lack the backing volume to follow through.
2. The Blackout Zone (T-30 Mins to T+30 Mins)
The Mechanic: This is "toxic flow." The initial spike is often driven by high-frequency algorithms executing on raw headline numbers before human digestion or revision analysis occurs. The first move is frequently a fake-out.
The Adjustment: Hard flat. No open positions, no working orders. "No heroics" is the exact right mindset. You cannot manage risk when slippage can gap past your stop loss in milliseconds.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: CPI week playbook: reduced size and wider filters
3. Post-CPI Digestion (T+1 Hour to T+24 Hours)
The Mechanic: The market needs to establish a new Initial Balance (IB) or Value Area. The headline number is irrelevant; the market's reaction to the headline is what dictates the next trend.
The Adjustment: Wait for a clear support/resistance level to hold on a higher timeframe (e.g., 1H or 4H candle close) before sizing back up. Let the institutional money show its hand first.
4. The Data Loop (Journaling cpi_week)
The Mechanic: This is the most professional part of your playbook. Expectancy ($ won per trade) is a function of edge. If your edge is trend-following or structural, CPI weeks inherently degrade that edge.
The Adjustment: By tagging these trades, you isolate the data. If you find your cpi_week expectancy is consistently negative, the math will objectively tell you to tighten your rules next month, removing emotion from the decision.
The Mechanic: The market needs to establish a new Initial Balance (IB) or Value Area. The headline number is irrelevant; the market's reaction to the headline is what dictates the next trend.
The Adjustment: Wait for a clear support/resistance level to hold on a higher timeframe (e.g., 1H or 4H candle close) before sizing back up. Let the institutional money show its hand first.
4. The Data Loop (Journaling cpi_week)
The Mechanic: This is the most professional part of your playbook. Expectancy ($ won per trade) is a function of edge. If your edge is trend-following or structural, CPI weeks inherently degrade that edge.
The Adjustment: By tagging these trades, you isolate the data. If you find your cpi_week expectancy is consistently negative, the math will objectively tell you to tighten your rules next month, removing emotion from the decision.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: CPI week playbook: reduced size and wider filters
Pine Script: CPI Week Playbook Assistant
To make this an "evergreen process," we can code these rules directly into your charts.
This Pine Script (v5) creates an on-chart assistant. You input the date and time of the next CPI release. The script will automatically color-code the background of your chart to visually enforce your playbook phases (Throttle, Blackout, Digestion) and display a dynamic dashboard reminding you of your rules.
To make this an "evergreen process," we can code these rules directly into your charts.
This Pine Script (v5) creates an on-chart assistant. You input the date and time of the next CPI release. The script will automatically color-code the background of your chart to visually enforce your playbook phases (Throttle, Blackout, Digestion) and display a dynamic dashboard reminding you of your rules.
Code: Select all
//@version=5
indicator("CPI Week Playbook [Evergreen]", overlay=true)
// =========================================================================
// INPUTS: Define the CPI Event and Playbook Parameters
// =========================================================================
grp1 = "Next CPI Event"
cpi_time = input.time(timestamp("2026-10-13 08:30:00"), title="Next CPI Date/Time", group=grp1)
grp2 = "Playbook Parameters"
throttle_days = input.int(2, title="Pre-CPI Throttle (Days)", group=grp2, tooltip="How many days before CPI to reduce size")
blackout_mins = input.int(30, title="Blackout Window (Mins)", group=grp2, tooltip="Minutes before/after release to be completely flat")
digest_hours = input.int(4, title="Post-CPI Digestion (Hours)", group=grp2, tooltip="Hours after blackout to wait for new balance")
// =========================================================================
// TIME MATH & LOGIC STATES
// =========================================================================
// Convert inputs to milliseconds for comparison
ms_per_day = 24 * 60 * 60 * 1000
ms_per_hour = 60 * 60 * 1000
ms_per_min = 60 * 1000
time_to_cpi = cpi_time - time
time_from_cpi = time - cpi_time
// Define States based on Playbook
is_throttle = (time_to_cpi <= (throttle_days * ms_per_day)) and (time_to_cpi > (blackout_mins * ms_per_min))
is_blackout = (math.abs(time_to_cpi) <= (blackout_mins * ms_per_min))
is_digest = (time_from_cpi > (blackout_mins * ms_per_min)) and (time_from_cpi <= (digest_hours * ms_per_hour))
is_normal = not is_throttle and not is_blackout and not is_digest
// =========================================================================
// VISUAL ZONES (Background Colors)
// =========================================================================
bg_color = is_throttle ? color.new(color.yellow, 85) :
is_blackout ? color.new(color.red, 80) :
is_digest ? color.new(color.blue, 85) : na
bgcolor(bg_color, title="Playbook Phases")
// =========================================================================
// DASHBOARD / HUD
// =========================================================================
var table playbook_hud = table.new(position.bottom_right, 2, 4, border_width = 1)
if barstate.islast
// Determine dynamic text based on state
string current_state = is_normal ? "NORMAL GRIND" : is_throttle ? "PRE-CPI THROTTLE" : is_blackout ? "HARD BLACKOUT" : "DIGESTION PHASE"
color state_color = is_normal ? color.green : is_throttle ? color.yellow : is_blackout ? color.red : color.blue
string rec_size = is_normal ? "100% (Full Size)" : is_throttle ? "50% (Size Down)" : is_blackout ? "FLAT (0%)" : "Scaling Up / Waiting"
string rec_filter = is_normal ? "Standard Spreads" : is_throttle ? "Wider go/no-go, limit pref" : is_blackout ? "Cancel all working orders" : "Wait for clear level hold"
// Header
table.cell(playbook_hud, 0, 0, "CPI PLAYBOOK", text_color=color.white, bgcolor=color.gray, text_halign=text.align_left)
table.cell(playbook_hud, 1, 0, "STATUS", text_color=color.white, bgcolor=color.gray, text_halign=text.align_center)
// Rows
table.cell(playbook_hud, 0, 1, "Current Phase:", text_color=color.white, bgcolor=color.black, text_halign=text.align_left)
table.cell(playbook_hud, 1, 1, current_state, text_color=color.white, bgcolor=state_color, text_halign=text.align_center)
table.cell(playbook_hud, 0, 2, "Position Size:", text_color=color.white, bgcolor=color.black, text_halign=text.align_left)
table.cell(playbook_hud, 1, 2, rec_size, text_color=color.white, bgcolor=color.black, text_halign=text.align_center)
table.cell(playbook_hud, 0, 3, "Spread Filter:", text_color=color.white, bgcolor=color.black, text_halign=text.align_left)
table.cell(playbook_hud, 1, 3, rec_filter, text_color=color.white, bgcolor=color.black, text_halign=text.align_center)Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: CPI week playbook: reduced size and wider filters
How to use this script:
1.) Open TradingView, go to the Pine Editor tab at the bottom.
2.) Paste the code and click Add to Chart.
3.) The Evergreen Step: At the start of every month, open the indicator settings (the gear icon on your chart) and type in the exact date and time of the upcoming CPI release.
4.) The script will automatically paint your chart yellow 48 hours before the print (reminding you to halve your size and widen filters), paint a red strip for the blackout zone, and a blue strip post-release reminding you to wait for a structural hold. A dashboard in the bottom right will explicitly tell you your permitted position size at any given moment.
1.) Open TradingView, go to the Pine Editor tab at the bottom.
2.) Paste the code and click Add to Chart.
3.) The Evergreen Step: At the start of every month, open the indicator settings (the gear icon on your chart) and type in the exact date and time of the upcoming CPI release.
4.) The script will automatically paint your chart yellow 48 hours before the print (reminding you to halve your size and widen filters), paint a red strip for the blackout zone, and a blue strip post-release reminding you to wait for a structural hold. A dashboard in the bottom right will explicitly tell you your permitted position size at any given moment.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: CPI week playbook: reduced size and wider filters
Since TradingView uses native background shading and MetaTrader relies on chart objects, the architecture for MT4 and MT5 requires drawing OBJ_RECTANGLE elements that project into the future.
To ensure the dashboard updates even when the order book completely dries up and ticks stop arriving, both scripts utilize OnTimer(1) to refresh the state every second, independently of price action.
MQL4 Implementation (Indicator)
To ensure the dashboard updates even when the order book completely dries up and ticks stop arriving, both scripts utilize OnTimer(1) to refresh the state every second, independently of price action.
MQL4 Implementation (Indicator)
Code: Select all
//+------------------------------------------------------------------+
//| CPI_Playbook_MT4.mq4 |
//+------------------------------------------------------------------+
#property copyright "Evergreen Playbook"
#property link ""
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 0
// =========================================================================
// INPUTS
// =========================================================================
input datetime CPI_Event_Date = D'2026.10.13 14:30'; // Next CPI Date (Broker Time!)
input int Throttle_Days = 2; // Pre-CPI Throttle (Days)
input int Blackout_Mins = 30; // Blackout Window (Mins)
input int Digest_Hours = 4; // Post-CPI Digestion (Hours)
// =========================================================================
// GLOBAL VARIABLES
// =========================================================================
string obj_throttle = "CPI_Zone_Throttle";
string obj_blackout = "CPI_Zone_Blackout";
string obj_digest = "CPI_Zone_Digest";
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
EventSetTimer(1); // Update HUD every second, even if ticks stop
DrawZones();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
Comment("");
ObjectDelete(0, obj_throttle);
ObjectDelete(0, obj_blackout);
ObjectDelete(0, obj_digest);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
// Update zone heights on new ticks to ensure they cover the screen
UpdateZoneHeights();
return(rates_total);
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
datetime now = TimeCurrent();
datetime throttle_start = CPI_Event_Date - (Throttle_Days * 86400);
datetime blackout_start = CPI_Event_Date - (Blackout_Mins * 60);
datetime blackout_end = CPI_Event_Date + (Blackout_Mins * 60);
datetime digest_end = blackout_end + (Digest_Hours * 3600);
string state, rec_size, rec_filter;
if(now >= throttle_start && now < blackout_start)
{
state = "PRE-CPI THROTTLE";
rec_size = "50% (Size Down)";
rec_filter = "Wider go/no-go, limit preference";
}
else if(now >= blackout_start && now <= blackout_end)
{
state = "HARD BLACKOUT";
rec_size = "FLAT (0%)";
rec_filter = "Cancel all working orders. No heroics.";
}
else if(now > blackout_end && now <= digest_end)
{
state = "DIGESTION PHASE";
rec_size = "Scaling Up / Waiting";
rec_filter = "Wait for clear level hold";
}
else
{
state = "NORMAL GRIND";
rec_size = "100% (Full Size)";
rec_filter = "Standard Spreads";
}
string hud = "\n=======================\n" +
" CPI WEEK PLAYBOOK \n" +
"=======================\n\n" +
"PHASE: " + state + "\n\n" +
"SIZE: " + rec_size + "\n" +
"FILTER: " + rec_filter + "\n";
Comment(hud);
}
//+------------------------------------------------------------------+
//| Draw Background Zones |
//+------------------------------------------------------------------+
void DrawZones()
{
datetime throttle_start = CPI_Event_Date - (Throttle_Days * 86400);
datetime blackout_start = CPI_Event_Date - (Blackout_Mins * 60);
datetime blackout_end = CPI_Event_Date + (Blackout_Mins * 60);
datetime digest_end = blackout_end + (Digest_Hours * 3600);
double top = 999999.0;
double bot = 0.0;
CreateRect(obj_throttle, throttle_start, blackout_start, clrYellow);
CreateRect(obj_blackout, blackout_start, blackout_end, clrRed);
CreateRect(obj_digest, blackout_end, digest_end, clrBlue);
}
void CreateRect(string name, datetime t1, datetime t2, color clr)
{
if(ObjectFind(0, name) < 0)
{
ObjectCreate(0, name, OBJ_RECTANGLE, 0, t1, 0, t2, 999999);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
}
void UpdateZoneHeights()
{
double max_price = ChartGetDouble(0, CHART_PRICE_MAX);
double min_price = ChartGetDouble(0, CHART_PRICE_MIN);
ObjectSetDouble(0, obj_throttle, OBJPROP_PRICE, 0, max_price);
ObjectSetDouble(0, obj_throttle, OBJPROP_PRICE, 1, min_price);
ObjectSetDouble(0, obj_blackout, OBJPROP_PRICE, 0, max_price);
ObjectSetDouble(0, obj_blackout, OBJPROP_PRICE, 1, min_price);
ObjectSetDouble(0, obj_digest, OBJPROP_PRICE, 0, max_price);
ObjectSetDouble(0, obj_digest, OBJPROP_PRICE, 1, min_price);
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: CPI week playbook: reduced size and wider filters
MQL5 Implementation (Indicator)
The MT5 version uses the updated OnCalculate signature and stricter type checking for chart properties.
The MT5 version uses the updated OnCalculate signature and stricter type checking for chart properties.
Code: Select all
//+------------------------------------------------------------------+
//| CPI_Playbook_MT5.mq5 |
//+------------------------------------------------------------------+
#property copyright "Evergreen Playbook"
#property link ""
#property version "1.00"
#property indicator_chart_window
#property indicator_plots 0
// =========================================================================
// INPUTS
// =========================================================================
input datetime CPI_Event_Date = D'2026.10.13 14:30'; // Next CPI Date (Broker Time!)
input int Throttle_Days = 2; // Pre-CPI Throttle (Days)
input int Blackout_Mins = 30; // Blackout Window (Mins)
input int Digest_Hours = 4; // Post-CPI Digestion (Hours)
// =========================================================================
// GLOBAL VARIABLES
// =========================================================================
string obj_throttle = "CPI_Zone_Throttle";
string obj_blackout = "CPI_Zone_Blackout";
string obj_digest = "CPI_Zone_Digest";
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
EventSetTimer(1);
DrawZones();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
Comment("");
ObjectDelete(0, obj_throttle);
ObjectDelete(0, obj_blackout);
ObjectDelete(0, obj_digest);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
UpdateZoneHeights();
return(rates_total);
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
datetime now = TimeCurrent();
datetime throttle_start = CPI_Event_Date - (Throttle_Days * 86400);
datetime blackout_start = CPI_Event_Date - (Blackout_Mins * 60);
datetime blackout_end = CPI_Event_Date + (Blackout_Mins * 60);
datetime digest_end = blackout_end + (Digest_Hours * 3600);
string state, rec_size, rec_filter;
if(now >= throttle_start && now < blackout_start)
{
state = "PRE-CPI THROTTLE";
rec_size = "50% (Size Down)";
rec_filter = "Wider go/no-go, limit preference";
}
else if(now >= blackout_start && now <= blackout_end)
{
state = "HARD BLACKOUT";
rec_size = "FLAT (0%)";
rec_filter = "Cancel all working orders. No heroics.";
}
else if(now > blackout_end && now <= digest_end)
{
state = "DIGESTION PHASE";
rec_size = "Scaling Up / Waiting";
rec_filter = "Wait for clear level hold";
}
else
{
state = "NORMAL GRIND";
rec_size = "100% (Full Size)";
rec_filter = "Standard Spreads";
}
string hud = "\n=======================\n" +
" CPI WEEK PLAYBOOK \n" +
"=======================\n\n" +
"PHASE: " + state + "\n\n" +
"SIZE: " + rec_size + "\n" +
"FILTER: " + rec_filter + "\n";
Comment(hud);
}
//+------------------------------------------------------------------+
//| Draw Background Zones |
//+------------------------------------------------------------------+
void DrawZones()
{
datetime throttle_start = CPI_Event_Date - (Throttle_Days * 86400);
datetime blackout_start = CPI_Event_Date - (Blackout_Mins * 60);
datetime blackout_end = CPI_Event_Date + (Blackout_Mins * 60);
datetime digest_end = blackout_end + (Digest_Hours * 3600);
CreateRect(obj_throttle, throttle_start, blackout_start, clrYellow);
CreateRect(obj_blackout, blackout_start, blackout_end, clrRed);
CreateRect(obj_digest, blackout_end, digest_end, clrDodgerBlue);
}
void CreateRect(string name, datetime t1, datetime t2, color clr)
{
if(ObjectFind(0, name) < 0)
{
ObjectCreate(0, name, OBJ_RECTANGLE, 0, t1, 0, t2, 999999);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
}
void UpdateZoneHeights()
{
double max_price = ChartGetDouble(0, CHART_PRICE_MAX);
double min_price = ChartGetDouble(0, CHART_PRICE_MIN);
ObjectSetDouble(0, obj_throttle, OBJPROP_PRICE, 0, max_price);
ObjectSetDouble(0, obj_throttle, OBJPROP_PRICE, 1, min_price);
ObjectSetDouble(0, obj_blackout, OBJPROP_PRICE, 0, max_price);
ObjectSetDouble(0, obj_blackout, OBJPROP_PRICE, 1, min_price);
ObjectSetDouble(0, obj_digest, OBJPROP_PRICE, 0, max_price);
ObjectSetDouble(0, obj_digest, OBJPROP_PRICE, 1, min_price);
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: CPI week playbook: reduced size and wider filters
Implementation Notes:
Broker Time Translation: The CPI_Event_Date input must map to your specific broker's server time, not local time or EST.
Zone Rendering: Background rectangles in MT4/MT5 require precise price coordinates. The UpdateZoneHeights() function continually dynamically queries the chart's upper and lower boundaries to stretch the colored zones top-to-bottom regardless of how far you scroll or scale the y-axis.
Data Logging: If you utilize an Expert Advisor to execute your 15m/daily structure scalps, you can bridge this logic by exporting the current state (e.g., via Global Variables) to automatically hard-code the cpi_week tag into your order comments or adjust your lot sizing logic programmatically.
Broker Time Translation: The CPI_Event_Date input must map to your specific broker's server time, not local time or EST.
Zone Rendering: Background rectangles in MT4/MT5 require precise price coordinates. The UpdateZoneHeights() function continually dynamically queries the chart's upper and lower boundaries to stretch the colored zones top-to-bottom regardless of how far you scroll or scale the y-axis.
Data Logging: If you utilize an Expert Advisor to execute your 15m/daily structure scalps, you can bridge this logic by exporting the current state (e.g., via Global Variables) to automatically hard-code the cpi_week tag into your order comments or adjust your lot sizing logic programmatically.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: CPI week playbook: reduced size and wider filters
This cTrader implementation takes advantage of native C# string interpolation and cAlgo's built-in Color.FromArgb method to render transparent background zones that don't obscure your candlesticks.
Just like the MT4/MT5 versions, it utilizes Timer.Start() rather than relying on the Calculate() tick loop, ensuring the dashboard dynamically updates even when market liquidity drops to zero before the print.
cTrader (C# cAlgo) Implementation
Implementation Notes:
Time Coordination: When entering the Next CPI string format in your cTrader parameters, ensure you align it with Server.Time (your broker's time), not your local time.
Chart Resizing: The UpdateZoneHeights() call inside OnTimer() queries Chart.BottomY and Chart.TopY every second. This ensures the background zones immediately resize to fit your vertical scale when you zoom in on 1m/5m price action setups.
Just like the MT4/MT5 versions, it utilizes Timer.Start() rather than relying on the Calculate() tick loop, ensuring the dashboard dynamically updates even when market liquidity drops to zero before the print.
cTrader (C# cAlgo) Implementation
Code: Select all
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class CpiPlaybookEvergreen : Indicator
{
// =========================================================================
// INPUTS
// =========================================================================
[Parameter("Next CPI (yyyy-mm-dd HH:mm)", DefaultValue = "2026-10-13 14:30", Group = "Event Details")]
public string CpiDateStr { get; set; } // Passed as string to avoid custom DateTime pickers, format matched to broker time
[Parameter("Pre-CPI Throttle (Days)", DefaultValue = 2, Group = "Playbook Parameters")]
public int ThrottleDays { get; set; }
[Parameter("Blackout Window (Mins)", DefaultValue = 30, Group = "Playbook Parameters")]
public int BlackoutMins { get; set; }
[Parameter("Post-CPI Digestion (Hours)", DefaultValue = 4, Group = "Playbook Parameters")]
public int DigestHours { get; set; }
private DateTime _cpiDate;
// =========================================================================
// INITIALIZATION
// =========================================================================
protected override void Initialize()
{
if (!DateTime.TryParse(CpiDateStr, out _cpiDate))
{
Print("Invalid CPI Date format. Please use 'yyyy-mm-dd HH:mm'");
return;
}
// Start a 1-second timer to update the HUD and Zone Heights independent of market ticks
Timer.Start(TimeSpan.FromSeconds(1));
DrawZones();
UpdateHUD();
}
public override void Calculate(int index)
{
// Left intentionally blank. Logic is entirely time-based.
}
protected override void OnTimer()
{
UpdateHUD();
UpdateZoneHeights();
}
// =========================================================================
// VISUAL ZONES
// =========================================================================
private void DrawZones()
{
DateTime throttleStart = _cpiDate.AddDays(-ThrottleDays);
DateTime blackoutStart = _cpiDate.AddMinutes(-BlackoutMins);
DateTime blackoutEnd = _cpiDate.AddMinutes(BlackoutMins);
DateTime digestEnd = blackoutEnd.AddHours(DigestHours);
// Using alpha blending (50) so the background doesn't hide the price action
DrawRect("CPI_Throttle", throttleStart, blackoutStart, Color.FromArgb(50, Color.Yellow));
DrawRect("CPI_Blackout", blackoutStart, blackoutEnd, Color.FromArgb(50, Color.Red));
DrawRect("CPI_Digest", blackoutEnd, digestEnd, Color.FromArgb(50, Color.DodgerBlue));
}
private void DrawRect(string name, DateTime t1, DateTime t2, Color clr)
{
var rect = Chart.DrawRectangle(name, t1, Chart.BottomY, t2, Chart.TopY, clr);
rect.IsFilled = true;
rect.IsInteractive = false; // Prevents accidental dragging/clicking while trading
}
private void UpdateZoneHeights()
{
// Dynamically stretches the zones to the top/bottom of the chart during scrolling/zooming
var throttle = Chart.FindObject("CPI_Throttle") as ChartRectangle;
if (throttle != null) { throttle.Y1 = Chart.BottomY; throttle.Y2 = Chart.TopY; }
var blackout = Chart.FindObject("CPI_Blackout") as ChartRectangle;
if (blackout != null) { blackout.Y1 = Chart.BottomY; blackout.Y2 = Chart.TopY; }
var digest = Chart.FindObject("CPI_Digest") as ChartRectangle;
if (digest != null) { digest.Y1 = Chart.BottomY; digest.Y2 = Chart.TopY; }
}
// =========================================================================
// DASHBOARD / HUD
// =========================================================================
private void UpdateHUD()
{
DateTime now = Server.Time;
DateTime throttleStart = _cpiDate.AddDays(-ThrottleDays);
DateTime blackoutStart = _cpiDate.AddMinutes(-BlackoutMins);
DateTime blackoutEnd = _cpiDate.AddMinutes(BlackoutMins);
DateTime digestEnd = blackoutEnd.AddHours(DigestHours);
string state, recSize, recFilter;
if (now >= throttleStart && now < blackoutStart)
{
state = "PRE-CPI THROTTLE";
recSize = "50% (Size Down)";
recFilter = "Wider go/no-go, limit preference";
}
else if (now >= blackoutStart && now <= blackoutEnd)
{
state = "HARD BLACKOUT";
recSize = "FLAT (0%)";
recFilter = "Cancel all working orders. No heroics.";
}
else if (now > blackoutEnd && now <= digestEnd)
{
state = "DIGESTION PHASE";
recSize = "Scaling Up / Waiting";
recFilter = "Wait for clear level hold";
}
else
{
state = "NORMAL GRIND";
recSize = "100% (Full Size)";
recFilter = "Standard Spreads";
}
string hud = $"=======================\n" +
$" CPI WEEK PLAYBOOK \n" +
$"=======================\n\n" +
$"PHASE: {state}\n\n" +
$"SIZE: {recSize}\n" +
$"FILTER: {recFilter}\n";
Chart.DrawStaticText("CPI_HUD", hud, VerticalAlignment.Bottom, HorizontalAlignment.Right, Color.White);
}
}
}Time Coordination: When entering the Next CPI string format in your cTrader parameters, ensure you align it with Server.Time (your broker's time), not your local time.
Chart Resizing: The UpdateZoneHeights() call inside OnTimer() queries Chart.BottomY and Chart.TopY every second. This ensures the background zones immediately resize to fit your vertical scale when you zoom in on 1m/5m price action setups.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.