Hi Guys,
So I'm new to trading algos, and fairly new to Python and C#. This may seem like a very basic question but don't find a way around it.
What I'm trying to develop is the RMO oscillator, which is kind of a rainbow indicator in which a SMA is made over another SMA, and that way over and over. This is what I've got at tradingview:
cm2(x) => sma(x,2)
ma1=cm2(close)
ma2=cm2(ma1)
ma3=cm2(ma2)
ma4=cm2(ma3)
ma5=cm2(ma4)
ma6=cm2(ma5)
ma7=cm2(ma6)
ma8=cm2(ma7)
ma9=cm2(ma8)
ma10=cm2(ma9)
SwingTrd1=100*(close-(ma1+ma2+ma3+ma4+ma5+ma6+ma7+ma8+ma9+ma10)/10)/ (highest(close,10)-lowest(close,10))
And this is what I've got in C# which I don't seem to make work because of operators, and probably my whole code:
symbolData.Sma1 = SMA(symbolData.Symbol, 2, res);
symbolData.Sma2 = symbolData.Sma1.SMA(2);
symbolData.Sma3 = symbolData.Sma2.SMA(2);
symbolData.Sma4 = symbolData.Sma3.SMA(2);
symbolData.Sma5 = symbolData.Sma4.SMA(2);
symbolData.Sma6 = symbolData.Sma5.SMA(2);
symbolData.Sma7 = symbolData.Sma6.SMA(2);
symbolData.Sma8 = symbolData.Sma7.SMA(2);
symbolData.Sma9 = symbolData.Sma8.SMA(2);
symbolData.Sma10 = symbolData.Sma9.SMA(2);
symbolData.SwingTrd1 = 100*(symbolData.Symbol-(symbolData.Sma1+symbolData.Sma2+symbolData.Sma3+symbolData.Sma4+symbolData.Sma5+symbolData.Sma6+symbolData.Sma7+symbolData.Sma8+symbolData.Sma9+symbolData.Sma10)/10)/(symbolData.window.Max-symbolData.window.Min);
My whole code is this:
namespace QuantConnect.Algorithm.CSharp
{
public class RMO: QCAlgorithm
{
//User variables
private int startingcash = 10000;
Resolution res = Resolution.Hour;
int rollingWindow = 10;
//Program Variables
public decimal usd;
Dictionary <string, SymbolData> Data= new Dictionary <string, SymbolData>();
List <string> FxSymbols = new List<string>
{ "EURUSD", "EURJPY", "GBPUSD", "EURGBP", "USDMXN"};
int numberOfSymbols =>FxSymbols.Count;
//Initialize Block
public override void Initialize()
{
SetStartDate(2019, 1, 1); //Set Start Date
SetEndDate(2019, 12, 8); //Set End Date
SetCash(startingcash); //Set Strategy Cash
foreach (var symbol in FxSymbols)
{
var Fx = AddForex(symbol, res, Market.Oanda);
Data.Add(symbol, new SymbolData(Fx.Symbol, Fx.BaseCurrencySymbol));
}
foreach (var key in Data)
{
var symbolData = key.Value;
symbolData.window = new RollingWindow<IndicatorDataPoint>(rollingWindow);
symbolData.Sma1 = SMA(symbolData.Symbol, 2, res);
symbolData.Sma2 = symbolData.Sma1.SMA(2);
symbolData.Sma3 = symbolData.Sma2.SMA(2);
symbolData.Sma4 = symbolData.Sma3.SMA(2);
symbolData.Sma5 = symbolData.Sma4.SMA(2);
symbolData.Sma6 = symbolData.Sma5.SMA(2);
symbolData.Sma7 = symbolData.Sma6.SMA(2);
symbolData.Sma8 = symbolData.Sma7.SMA(2);
symbolData.Sma9 = symbolData.Sma8.SMA(2);
symbolData.Sma10 = symbolData.Sma9.SMA(2);
symbolData.SwingTrd1 = 100*(symbolData.Symbol-(symbolData.Sma1+symbolData.Sma2+symbolData.Sma3+symbolData.Sma4+symbolData.Sma5+symbolData.Sma6+symbolData.Sma7+symbolData.Sma8+symbolData.Sma9+symbolData.Sma10)/10)/(symbolData.window.Max-symbolData.window.Min);
symbolData.SwingTrd2 = symbolData.SwingTrd_0.EMA(30);
symbolData.SwingTrd3 = symbolData.SwingTrd2.EMA(30);
}
SetBrokerageModel(BrokerageName.OandaBrokerage, AccountType.Margin);
}
//On Data Block
public override void OnData(Slice data)
{
foreach (var symbolData in Data.Values)
{
if(symbolData.SwingTrd3.IsReady)
{
usd = Portfolio.CashBook["USD"].Amount;
if(!Portfolio[symbolData.Symbol].Invested)
{
//BUY SIGNAL
if(symbolData.SwingTrd2 > symbolData.SwingTrd3)
{
MarketOrder(symbolData.Symbol, 1000);
Log($"BUY {symbolData.Symbol} at {data[symbolData.Symbol].Price}");
}
}
if(Portfolio[symbolData.Symbol].Invested)
{
var holding = Portfolio.CashBook[symbolData.BaseSymbol].Amount;
if(symbolData.SwingTrd2 < symbolData.SwingTrd3)
{
//PLACE SELL ORDER
MarketOrder(symbolData.Symbol, -holding);
Log($"SELL {symbolData.Symbol} at {data[symbolData.Symbol].Price}");
}
}
}
}
}
//CUSTOM CLASS
public class SymbolData
{
public Symbol Symbol;
public string BaseSymbol;
public RollingWindow<IndicatorDataPoint> window;
public SimpleMovingAverage Sma1;
public SimpleMovingAverage Sma2;
public SimpleMovingAverage Sma3;
public SimpleMovingAverage Sma4;
public SimpleMovingAverage Sma5;
public SimpleMovingAverage Sma6;
public SimpleMovingAverage Sma7;
public SimpleMovingAverage Sma8;
public SimpleMovingAverage Sma9;
public SimpleMovingAverage Sma10;
public string SwingTrd1;
public ExponentialMovingAverage SwingTrd2;
public ExponentialMovingAverage SwingTrd3;
public SymbolData(Symbol symbol, string baseSymbol)
{
Symbol = symbol;
BaseSymbol = baseSymbol;
}
}
}
}
I'm thinking that I probably have to use a RollingWindow to do the SwingTrd1. Can someone help me work a way around for the symbolData.SwingTrd1?
Thanks in advance.
Alexandre Catarino
Hi Ricardo Sandoval ,
SwingTrd1 is defined as string where it should be IndicatorBase<IndicatorDataPoint>.
For a summation of indicators, you can use the Plus method:
symbolData.SwingTrd1 = symbolData.Sma1.Plus( symbolData.Sma2.Plus( symbolData.Sma3.Plus( symbolData.Sma4.Plus( symbolData.Sma5.Plus( symbolData.Sma6.Plus( symbolData.Sma7.Plus( symbolData.Sma8.Plus( symbolData.Sma9.Plus( symbolData.Sma10))))))))); symbolData.SwingTrd2 = symbolData.SwingTrd1.EMA(30); symbolData.SwingTrd3 = symbolData.SwingTrd2.EMA(30);
We can use the .Multiply and .Over method to add the multiplication by 100 and the division for 10. However, I am not sure that the range of window maximum and minimum will work.
Why not create a method in SymbolData that calculates SwingTrd1, SwingTrd2, SwingTrd3 on demand?
Ricardo Sandoval
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!