Big changes have happened and will continue to happen as we move into the New Year.
One, the Futures Performance Page Portfolio (PPP) had an incredible year. The case for Futures over Forex is strong and the PPP really slammed that idea home. Fx is still good if you have a good broker, but Futures might be better.
Two, I developed a deep hatred of losing in 2024. It borders on psychotic. I can’t stand drawdowns. I can’t stand recommending a trading system and have it take losing trades for the person who’s using it.
A long time ago, I wondered about “trading for a living.” It seems like the best thing in the world and that’s why I’ve been hooked for so long. But something has always bothered me.
From Day 1.
“How do we trade for a living or retire from our job if our trading system has losing months or losing years?”
As a trader, there’s no good answer to this.
And I’ve ignored it for over a decade, even as this worrisome thought kept burrowing into my skull.
But guess what? High income every week or every month solves that problem.
My ETFs are down today? So what, they pay me. My ETFs are having a bad month? So what, they pay me.
It’s become quite clear to me that it’s possible to pay bills every month–if we have money coming in every month.
Trading will never be able to fulfill that promise.
And that’s a revolutionary revelation.
But we can take it one step further.
If we have income coming in every week/month, we can stop worrying. At that point, what could we do? Use a trading system! Trading systems are best if we never care how they do. And having a high income coming in allows us to do just that.
So trading isn’t a bad thing. It just might be a complementary thing. And that potential realization has changed everything for me.
So we’ll continue with our systems. That’s not going to change. But you will be hearing a lot more about high-yield instruments. Feel free to ask questions anytime.
I’m very much looking forward to 2025. Happy New Year!
Scott
January 2025
This is the only block of code needed for the 5M RSI Robot. Copy the code below and load into Tradestation. Then put it on the chart and test it to make sure it works properly.
ES.D 5-Minute RSI (No daytrading)
inputs:
Price(Close),
Length(14),
OverBought(75),
ExTime(1620),
TP(1000),
SL(400);
var:
MyRSI(0);
// Calculate the RSI value
MyRSI = RSI(Price, Length);
// Check if RSI crosses over the OverBought level
if CurrentBar > 1 and MyRSI crosses over OverBought then begin
// CB > 1 check used to avoid spurious cross confirmation at CB = 1
Buy("RsiMomLE") next bar at market;
end;
// Exit the position at the specified expiration time
if MarketPosition = 1 and Time = ExTime then
Sell next bar at market;
if MarketPosition = -1 and Time = ExTime then
Buy to Cover next bar at market;
// Set profit target and stop loss
SetProfitTarget(TP);
SetStopLoss(SL);
// Disable further contracts once the position is closed
SetStopContract;
Your Report from 2016-January 2024 should look similar to this:
The next robot, the Daily ES.D RSI, needs TWO blocks of code. They need to be separate. Use one for a strategy called ES.D Daily RSI LE (Long Entry) and one for the exit called ES.D Daily RSI LX (Long Exit). Load both of those onto your Daily chart and it should work perfectly. Here's a screenshot of what that looks like:
{ Long Entry }
inputs:
Price(Close),
Length(2),
OverSold(10),
OverBought(70),
MALength(100);
var:
MyRSI(0);
// Check if price is above the moving average
if close > AverageFC(close, MALength) then begin
// Calculate RSI
MyRSI = RSI(Price, Length);
// Check if RSI crosses over OverSold level and is below OverBought
if CurrentBar > 1 and MyRSI crosses over OverSold and MyRSI < OverBought then begin
// CB > 1 check used to avoid spurious cross confirmation at CB = 1
Buy("RsiLE") next bar at market;
end;
end;
inputs:
Price(Close),
Length(2),
OverBought(70);
var:
MyRSI(0);
// Calculate the RSI value
MyRSI = RSI(Price, Length);
// Check if RSI crosses over the OverBought level
if CurrentBar > 1 and MyRSI crosses over OverBought then begin
// CB > 1 check used to avoid spurious cross confirmation at CB = 1
Sell("RsiLX") next bar at market;
end;
Your Report from 2016-January 2024 should look similar to this:
The next robot, the 240M ES.D CCI, needs THREE blocks of code. They need to be separate. Use one for a strategy called ES.D 240M CCI LE (Long Entry) and one for the exit called ES.D 240M CCI LX (Long Exit). Load all of those onto your Daily chart and it should work perfectly. Here's a screenshot of what that looks like:
ES.D 240M CCI LE (ENTRY)
ES.D 240-Minute CCI LE (Every Trading Day Except Sunday; Settings here: https://app.screencast.com/PWUQUZ0EZecq9)
inputs:
Trading_Days("Trading Days"),
Trade_Sunday_0_1(0),
Trade_Monday_0_1(1),
Trade_Tuesday_0_1(1),
Trade_Wednesday_0_1(1),
Trade_Thursday_0_1(1),
Trade_Friday_0_1(1),
Trade_Times("Trade Times"),
StartTime(0),
EndTime(2400),
CCI("CCI"),
Price(Close),
CCILength(19),
OverSold(-100),
Mov_Avg("Mov Avg"),
MALength(100);
var: DayOK(false), MyCCI(0), MA(0), EntryTimes(false);
// Determine if trading is allowed based on the day of the week and the input flags
if dayofweek(date) = 0 and Trade_Sunday_0_1 = 1 then
DayOK = true
else if dayofweek(date) = 1 and Trade_Monday_0_1 = 1 then
DayOK = true
else if dayofweek(date) = 2 and Trade_Tuesday_0_1 = 1 then
DayOK = true
else if dayofweek(date) = 3 and Trade_Wednesday_0_1 = 1 then
DayOK = true
else if dayofweek(date) = 4 and Trade_Thursday_0_1 = 1 then
DayOK = true
else if dayofweek(date) = 5 and Trade_Friday_0_1 = 1 then
DayOK = true
else
DayOK = false;
// Calculate the moving average and CCI
MA = AverageFC(Price, MALength);
MyCCI = CCI(CCILength);
// Check if we are within the specified trade times
EntryTimes = Time >= StartTime and Time <= EndTime;
// Define the condition for the trade: CCI crosses under Oversold, price above MA, within trade time, and valid day
condition1 = close > MA;
if CurrentBar > 1 and MyCCI crosses under OverSold and condition1 and EntryTimes and DayOK = true then
Buy("CCILE") next bar at market;
inputs:
PT_ATR(1.1),
SL_ATR(9),
ATRLength(14);
var:
PT_LXP(0),
SL_LXP(0),
ATRCalc(0);
// Calculate the Average True Range (ATR)
ATRCalc = AvgTrueRange(ATRLength);
// Determine profit target and stop loss based on market position
if marketposition = 0 then begin
// No position: Set targets based on the next bar's open price
PT_LXP = Open next bar + ATRCalc * PT_ATR;
SL_LXP = Open next bar - ATRCalc * SL_ATR;
end
else begin
// Position is open: Set targets based on the entry price
PT_LXP = EntryPrice + ATRCalc * PT_ATR;
SL_LXP = EntryPrice - ATRCalc * SL_ATR;
end;
// Set sell orders for profit target and stop loss
Sell next bar at PT_LXP limit;
Sell next bar at SL_LXP stop;
inputs: BarToExitOn(74) {
DisplayName = "BarToExitOn",
ToolTip = "Enter the number of bars since entry at which to exit the position."
};
if BarsSinceEntry = BarToExitOn then
Sell("TimeBarsLX") next bar at market;
The Report for the 240M CCI from 2016-January 2024 should look similar to this:
// Inputs
Inputs:
tod(1300), // Time of day for trade execution
dowe(1), // Day of the week for entry (1 = Monday)
dowex(3), // Day of the week for exit (3 = Wednesday)
stopATR(17), // Stop loss multiplier based on ATR
targetATR(1.3), // Profit target multiplier based on ATR
ATRlength(29); // ATR calculation length
// Notes:
// - This is for a 15-minute chart with `@NQ.D` as the primary data.
// - It can be adapted for other indexes, such as `@ES.D` or `@YM.D`.
// Entry Logic
If DayOfWeek(Date) = dowe and
Time = tod then
Buy next bar at market;
// Exit Logic
If DayOfWeek(Date) = dowex and
Time = tod then
Sell next bar at market;
// Risk Management
SetStopContract;
SetStopLoss(stopATR * AvgTrueRange(ATRlength) * BigPointValue);
SetProfitTarget(targetATR * AvgTrueRange(ATRlength) * BigPointValue);
Curve Since 2000:
Code for Buy Monday With a Twist
// Inputs
Inputs:
tod(1410), // Time of day to evaluate entry for buying
dowe(1), // Day of the week for entry (1 = Monday)
dowex(3), // Day of the week for exit (3 = Wednesday)
mafilt(50), // Moving average filter length for data2
outtime(930), // Time of day for exit
stopATR(15), // Stop loss multiplier based on ATR
targetATR(1.4), // Profit target multiplier based on ATR
ATRlength(41); // ATR calculation length
// Notes:
// - This is for a 10-minute chart with `@NQ.D` as the primary data.
// - Data2 should be a daily chart of `@NQ.D` (Go to Data >> Add Symbol).
// Entry Logic
If DayOfWeek(Date) = dowe and
Time = tod and
Close of Data2 < Average(Close of Data2, mafilt) then
Buy next bar at market;
// Exit Logic
If DayOfWeek(Date) = dowex and
Time = outtime then
Sell next bar at market;
// Risk Management
SetStopContract;
SetStopLoss(stopATR * AvgTrueRange(ATRlength) * BigPointValue);
SetProfitTarget(targetATR * AvgTrueRange(ATRlength) * BigPointValue);
Curve Since 2001:
// Inputs
Inputs:
BollingerPrice(Close), // Price used for Bollinger Band calculations
TestPriceLBand(Close), // Price to test against Bollinger Bands
Length(100), // Bollinger Band length
NumDevsUp(2), // Number of standard deviations for the upper band
NumDevsDn(3.1), // Number of standard deviations for the lower band
TP(3000), // Profit target
SL(1000), // Stop loss
BollingerPriceL(Close), // Price for lower band calculation
BollingerPriceS(Close); // Price for upper band calculation
// Variables
Variables:
UpperBand(0), // Upper Bollinger Band value
LowerBand(0); // Lower Bollinger Band value
// Calculations
UpperBand = BollingerBand(BollingerPriceL, Length, +NumDevsUp); // Calculate upper band
LowerBand = BollingerBand(BollingerPriceS, Length, -NumDevsDn); // Calculate lower band
// Entry Logic
If CurrentBar > 1 and TestPriceLBand crosses over UpperBand then
Buy("BkoutLE") next bar at UpperBand stop;
If CurrentBar > 1 and TestPriceLBand crosses under LowerBand then
SellShort("BkoutSE") next bar at LowerBand stop;
// Risk Management
SetStopContract;
SetProfitTarget(TP);
SetStopLoss(SL);
// Inputs
Inputs:
stopATR(9.5), // Stop loss multiplier based on ATR
targetATR(0.8), // Profit target multiplier based on ATR
ATRlength(14), // Length of ATR calculation
Length(20), // Length for additional logic (not used here)
OverBought(200), // Overbought level for CCI
// Trade Times
StartTime(0), // Start time for trades
EndTime(2400), // End time for trades
// CCI Settings
Price(Close), // Price used for CCI calculation
CCILength(24), // Length of the CCI calculation
OverSold(-100), // Oversold level for CCI
// Moving Average
MALength(40); // Length of moving average calculation
// Variables
Variables:
MyCCI(0), // Current CCI value
MA(0), // Current moving average value
EntryTimes(False); // True if within allowed trade times
// Calculations
MA = AverageFC(Price, MALength); // Calculate moving average
MyCCI = CCI(CCILength); // Calculate CCI
EntryTimes = Time >= StartTime and Time <= EndTime; // Check trade time window
// Conditions
condition1 = Close > MA; // Check if the close is above the moving average
// Entry Logic
If CurrentBar > 1 and MyCCI crosses under OverSold and condition1 and EntryTimes then
Buy("CCILE") next bar at market;
// Exit Logic
If MyCCI crosses over OverBought then
Sell("CCILX") next bar at market;
// Risk Management
SetProfitTarget(targetATR * AvgTrueRange(ATRlength) * BigPointValue);
SetStopLoss(stopATR * AvgTrueRange(ATRlength) * BigPointValue);
// Inputs
Inputs:
tod(1350), // Time of day to trigger trades
dowe(1), // Day of the week to enter a buy trade (e.g., Monday)
dowex(3), // Day of the week to enter a sell trade (e.g., Wednesday)
stopATR(20), // Stop loss multiplier based on ATR
targetATR(1.5), // Profit target multiplier based on ATR
ATRlength(14); // Length of the ATR calculation
// Entry logic for buy trades
If DayOfWeek(Date) = dowe and Time = tod then
Buy next bar at market;
// Entry logic for sell trades
If DayOfWeek(Date) = dowex and Time = tod then
Sell next bar at market;
// Risk management
SetStopContract;
SetStopLoss(stopATR * AvgTrueRange(ATRlength) * BigPointValue);
SetProfitTarget(targetATR * AvgTrueRange(ATRlength) * BigPointValue);
// Inputs
Inputs:
BollingerPrice(Close),
TestPriceLBand(Close),
Length(20),
NumDevsUp(2.2),
TP(900),
SL(1000),
BollingerPriceL(Close),
BollingerPriceS(Close);
// Variables
Variables:
UpperBand(0);
// Calculate Upper Bollinger Band
UpperBand = BollingerBand(BollingerPriceL, Length, NumDevsUp);
// Entry logic
If CurrentBar > 1 and TestPriceLBand crosses over UpperBand then
begin
Buy("BkoutLE") next bar at UpperBand stop;
SetStopContract;
SetProfitTarget(TP);
SetStopLoss(SL);
end;