NexusFi: Find Your Edge


Home Menu

 





Relative Strength in Ninja Trader


Discussion in NinjaTrader

Updated
    1. trending_up 3,537 views
    2. thumb_up 0 thanks given
    3. group 1 followers
    1. forum 1 posts
    2. attach_file 0 attachments




 
Search this Thread
  #1 (permalink)
oyz79
St Paul Minnesota
 
Posts: 1 since Oct 2012
Thanks Given: 0
Thanks Received: 0

I am trying to construct a relative strength multi-asset, multi time frame strategy and I am not a programmer. The strategy wizard will not perform this task. I did find a very similar strategy on the NT support forum using SPDRs and relative strength.

However, I am looking to remove the references to SMAs and simply rank multiple instruments based on their relative returns over the past x days. Go long (or short) the top ranked instrument over the past x days and hold for y days.

That strategy is below:

#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Data;
using NinjaTrader.Indicator;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Strategy;
#endregion

// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
/// <summary>
/// RS Rotation strategy using Sector SPDRs
/// </summary>
[Description("RS Rotation strategy using Sector SPDRs")]
public class SPDRRotation : Strategy
{
#region Variables
// Wizard generated variables
private int fastMA = 8; // Default setting for FastMA
private int slowMA = 15; // Default setting for SlowMA
private int funds = 2; // Default setting for Funds
private int sellRank = 4; // Default setting for SellPositionThr
private int SPYHedgeFactor = 200; //Default setting for SPY MA to use as hedge line
//private double StopLevel = 0.05;
// User defined variables (add any user defined variables below)
#endregion

//User defined variables
private int FundsHeld = 0;
private double Cash;
private double[] RelStr = new double[9];//Holds the calculated relative strength of each ETF
private int[] RankByBars = new int[9]; //Holds the RS rank of each bar object by barsArray index
private int[] BarsByRank = new int[9]; //Holds the barsArray index by RS Rank

/// <summary>
/// This method is used to configure the strategy and is called once before any strategy method is called.
/// </summary>
protected override void Initialize()
{
//Add weekly bars of Sector SPDRs
Add("XLV", PeriodType.Day, 1); // Health Care
Add("XLY", PeriodType.Day, 1); // Consumer Discretionary
Add("XLI", PeriodType.Day, 1); // Industrials
Add("XLU", PeriodType.Day, 1); // Utilities
Add("XLK", PeriodType.Day, 1); // Technology
Add("XLB", PeriodType.Day, 1); // Basic Materials
Add("XLE", PeriodType.Day, 1); // Energy
Add("XLF", PeriodType.Day, 1); // Financials
Add("XLP", PeriodType.Day, 1); // Consumer Staples

EntryHandling = EntryHandling.UniqueEntries;
CalculateOnBarClose = true;

AccountSize = 10000; //Starting Account Value

Cash = AccountSize; //Account Starts in all cash
FundsHeld = 0; //Account Starts holding no funds
}

/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate()
{
if (BarsInProgress != 0)
return;

//Print(Time[0].DayOfWeek.ToString() + " " + Time[0].Date.ToString());

//Every Thursday, rank each ETF, enter sell orders which close on Friday
if(Time[0].DayOfWeek == DayOfWeek.Thursday)
{
for(int i = 0; i < 9; i++) // calculate rank of i-th SPDR
{
RelStr[i] = SMARatioRelStr(BarsArray[i+1], FastMA, SlowMA).Plot0[0];
//Print(SMARatioRelStr(BarsArray[i+1], FastMA, SlowMA).Plot0[0]);
}

//Calculate the rank of each etf
for(int i = 0; i < 9; i++) // calculate rank of i-th SPDR
{
RankByBars[i] = 0;
for(int j = 0; j < 9; j++) // compare i-th SPDR to j-th SPDR
{
if(RelStr[i] < RelStr[j])
{
RankByBars[i]++; //Increment the rank if the ETF has a weaker RS
}
}
BarsByRank[RankByBars[i]] = i; // fills Bars by Rank
}

//Sell the weak ETFs that fall below the sell rank
for(int p = 0; p < 9; p++)
{
//If long an ETF and this ETF's rank falls below the sell rank
//Exit the position
if((Positions[p+1].Quantity > 0) && (RankByBars[p] > sellRank))
{
ExitLong(p+1,Positions[p+1].Quantity,"","");
FundsHeld--;
}
}
}
if(Time[0].DayOfWeek == DayOfWeek.Friday)
{
//Buy ETF highest ranked ETFs that aren't already owned
int k = 0; //Points to highest ranked ETF in BarsByRank[]
double CashPerPosition = Cash/(funds-FundsHeld); //Allocate all available cash to unfilled positions

//While there are empty positions and the S&P is above its HedgeMA SMA
//Fill the empty positions
while((FundsHeld < funds) && (Close[0] > SMA(SPYHedgeFactor)[0]))
{
//if we have a flat position with the top ranked bar
if(Positions[BarsByRank[k]+1].Quantity == 0)
{
//Scale quantity by 95% to account for price flucuation from the previous close
EnterLong(BarsByRank[k]+1,(int)(0.95*CashPerPosition/Closes[BarsByRank[k]+1][0]), "");
FundsHeld++;
}
k++; // Move to the next ranked ETF
}
}
}

#region OnExecutionFunction
protected override void OnExecution(IExecution execution)
{
if(execution.Name.CompareTo("Buy")==0)
{
//Adjust cash for buys
Cash = Cash - execution.Price * execution.Quantity - execution.Commission;
}
else if(execution.Name.CompareTo("Sell")==0)
{
//Adjust cash for sells
Cash = Cash + execution.Price * execution.Quantity - execution.Commission;
}
}
#endregion

#region Properties
[Description("Fast Moving Average used for RS")]
[Category("Parameters")]
public int FastMA
{
get { return fastMA; }
set { fastMA = Math.Max(1, value); }
}

[Description("Slow Moving Average used for RS")]
[Category("Parameters")]
public int SlowMA
{
get { return slowMA; }
set { slowMA = Math.Max(1, value); }
}

[Description("Number of Funds to Hold")]
[Category("Parameters")]
public int Funds
{
get { return funds; }
set { funds = Math.Max(1, value); }
}

[Description("Rank to Sell Out")]
[Category("Parameters")]
public int SellPositionThr
{
get { return sellRank; }
set { sellRank = Math.Max(2, value); }
}
[Description("SPY Moving Average to use as Hedge indicator")]
[Category("Parameters")]
public int HedgeMA
{
get { return SPYHedgeFactor; }
set { SPYHedgeFactor = Math.Max(1, value); }
}
/*
[Description("Percentage Level Below close to set stop loss order")]
[Category("Parameters")]
public double StopLoss
{
get { return StopLevel; }
set { StopLevel = Math.Min(0.20, value); }
}*/
#endregion
}
}


Reply With Quote

Can you help answer these questions
from other members on NexusFi?
Ceasefire in Name Only: Three Numbers That Define the Ir …
Prediction Markets & Event Contracts
One Wallet Made $200K in Hours: AP Probes Polymarket Cea …
Prediction Markets & Event Contracts
Q1 2026 Shatters All Derivatives Volume Records -- CME H …
Traders Hideout
Asia Equities Crash Overnight -- Nikkei -5.2%, KOSPI -6. …
Traders Hideout
$500M Riding on World Cup 2026: France/Spain Co-Favored …
Prediction Markets & Event Contracts
 
Best Threads (Most Thanked)
in the last 7 days on NexusFi
Sober Journey With S&P
24 thanks
2026 Jlab journal
10 thanks
Lady Vols Primer: Trading Volatility Journal
7 thanks
Algo automated / semi-automated trading anyone?
6 thanks
Trying to learn Volume and price action correlation
5 thanks




Last Updated on October 30, 2012


© 2026 NexusFi®, s.a., All Rights Reserved.
Av Ricardo J. Alfaro, Century Tower, Panama City, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada)
All information is for educational use only and is not investment advice. There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
About Us - Contact Us - Site Rules, Acceptable Use, and Terms and Conditions - Downloads - Top
no new posts