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
}
}
|