using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
/*
Risk Management
total Cash : 10.000 Euro or Dollar = tradeCashAllocation
trade 5 Stocks (=NumberStocksInPorftfolio)
per trade risk 80 % of tradeCashAllocation / maxallowedStocks
actula number NumberStocksInPorftfolio
reinvest profit tradeCashAllocation += netprofit
*/
namespace QuantConnect.Algorithm.CSharp
{
public class RSI_Algorithm : QCAlgorithm
{
//region "Variables"
Resolution _resolution=Resolution.Daily;
private const decimal minPrice = 5;
private const decimal minVolume = 500000m;
private const decimal tpPercent = 1.0m;
private bool _Once = true;
private const int rsiPeriods = 14;
private const int lSMALen = 8;
private int NumberStocksInPorftfolio = 0;
private decimal tradeCashAllocation = 50000m;
// dictionary to easily access SymbolData class parameters
// private readonly Dictionary<Symbol, SymbolData> Data = new Dictionary<Symbol, SymbolData>();
private readonly Dictionary<string, SymbolData> SymbData = new Dictionary<string, SymbolData>();
private SecurityChanges sChanges = SecurityChanges.None;
string ETF_symbol = "SPY";
DateTime sampledToday = DateTime.Now;
decimal price = 0;
// this is the ticket from our market order (entrance)
// private OrderTicket MarketTicket;
private const decimal MaximumLeverage = 4;
private const int maxallowedStocks = 5;
// this is the ticket from our stop loss order (exit)
private OrderTicket StopLossTicket;
public override void Initialize()
{
UniverseSettings.Resolution = _resolution;
UniverseSettings.Leverage = 1;
SetStartDate(2014, 08, 20);
SetEndDate(2014, 11, 30);
SetCash(tradeCashAllocation);
// SetWarmup(rsiPeriods);
AddSecurity(SecurityType.Equity, ETF_symbol, _resolution);
// Add_SymbolData(ETF_symbol);
AddUniverse(coarse =>
{
return (from cf in coarse
where cf.Price > minPrice
where cf.Volume > minVolume
// orderby cf.Price descending
orderby cf.Volume descending
select cf.Symbol).Take(15);
});
//list_universe_menbers()
}
public void OnData(TradeBars data)
{
Debug(string.Join(",", data.Keys));
decimal orderSize = 0;
// var securitiesWithHoldings;
//Debug("30) ");
// Debug("1) " + Time.Date.ToShortDateString() + " " + Stock.Symbol + " hSMA=" + SymbData[Stock.Symbol].hSMA + " iRSI="+ SymbData[Stock.Symbol].iRSI + " SymDate Count=" + SymbData.Count.ToString());
if (sChanges == SecurityChanges.None) return;
if (IsWarmingUp) return;
if ( _Once)
{
_Once = false;
Debug("Once: list members ");
list_universe_menbers();
}
foreach (var Stock in SymbData.Values)
{
// Debug("10) Suche in data " + Stock.Symbol);
//Debug("01) " + Time.Date.ToShortDateString() + " " + Stock.Symbol );
if (! data.ContainsKey(Stock.Symbol) ) {
Debug("10) not found in data " + Stock.Symbol);
if (search_universe_menbers(Stock.Symbol) == false)
Debug("11) not found in unives " + Stock.Symbol);
if (search_universe_menbers(Stock.Symbol) == true)
Debug("12) but found in unives " + Stock.Symbol);
// list_universe_menbers();
// var securitiesWithHoldings = Securities.Values.ToList();
var securitiesWithHoldings = data.Values.ToList();
var fi = securitiesWithHoldings.Count;
Debug (" count data.Values=" + fi );
foreach (var x in data.Values) {
// Debug(" -- actual symbol in data=" + x.Symbol ); //+ " " + x.IsReady ); // if (symbolData.IsReady
}
continue;
}
// Debug("40) ");
//One data point per day:
if (sampledToday.Date == data[Stock.Symbol].Time.Date) return;
// sampledToday = data[Stock.Symbol].Time;
// Debug("20) " + Time.Date.ToShortDateString());
if (data.ContainsKey(Stock.Symbol))
{
Stock.hSMA.Update(Time, data[Stock.Symbol].Close);
Stock.iRSI.Update(Time, data[Stock.Symbol].Close);
}
// Debug("50) ");
//Only take one data point per day (opening price)
price = Securities[Stock.Symbol].Close;
Securities[Stock.Symbol].SetLeverage(1m);
var securitiesWithHoldings2 = Securities.Values.Where(sec => sec.HoldStock).ToList();
NumberStocksInPorftfolio = securitiesWithHoldings2.Count;
// Debug("11) " + Time.Date.ToShortDateString() + " " + Stock.Symbol + " hSMA="+ SymbData[Stock.Symbol].hSMA + " iRSI="+ SymbData[Stock.Symbol].iRSI + " SymDate Count=" + SymbData.Count.ToString());
// Portfolio["IBM"].LastTradeProfi
// expect capture 10% of the daily range
//var shares = 3;
//shares = (int)Math.Floor(Portfolio.Cash / data["MSFT"].Close);
if ( Portfolio[Stock.Symbol].Invested) {
Debug(" Stocks in Portfolio=" + NumberStocksInPorftfolio + " Invested:" + Stock.Symbol + " price=" + price + " Invested=" + Portfolio[Stock.Symbol].Invested);
Log(" Stocks in Portfolio=" + NumberStocksInPorftfolio + " Invested:" + Stock.Symbol + " price=" + price + " Invested=" + Portfolio[Stock.Symbol].Invested);
}
if ( !Portfolio[Stock.Symbol].Invested && Stock.iRSI == 0m) {
Debug(" Error Stock.iRSI == 0m ; Count=" + NumberStocksInPorftfolio + " " + Stock.Symbol + " Cash=" + Portfolio.Cash + " iRSI="+ SymbData[Stock.Symbol].iRSI );
Log(" Error Stock.iRSI == 0m ; Count=" + NumberStocksInPorftfolio + " " + Stock.Symbol + " Cash=" + Portfolio.Cash + " iRSI="+ SymbData[Stock.Symbol].iRSI );
}
//foreach (var other_stock in Portfolio.Values)
//{
//if ( Portfolio[other_stock.Symbol].Invested && Stock.iRSI == 0m)
// Debug(" Count=" + NumberStocksInPorftfolio + " " + other_stock.Symbol + " Cash=" + Portfolio.Cash );
//}
Debug("Trace x-> " + Time.Date.ToShortDateString() + " Cash=" + Portfolio.Cash + " " + Stock.Symbol + " hSMA=" + Stock.hSMA + " iRSI=" + Stock.iRSI + " orderSize=" + orderSize + " price=" + Securities[Stock.Symbol].Close);
// --------------- BUY --------------------------------------
if ( !Portfolio[Stock.Symbol].Invested && Stock.iRSI < 32.0m && NumberStocksInPorftfolio < maxallowedStocks+1)
{
if (LiveMode) {
tradeCashAllocation = 10000m;
}
orderSize = Math.Floor((tradeCashAllocation * 0.6m / maxallowedStocks) / Securities[Stock.Symbol].Close);
var CashperStock = tradeCashAllocation * 0.6m / maxallowedStocks;
Debug("Buy x-> " + Time.Date.ToShortDateString() + " " + Stock.Symbol + " CashperStock= " + CashperStock + " " + CashperStock/price ) ;
//MarketTicket = StopMarketOrder(Stock.Symbol, orderSize, price * 0.97m); // 0.95m);
Debug("Buy x-> " + Time.Date.ToShortDateString() + " " + Stock.Symbol + " hSMA=" + Stock.hSMA + " iRSI=" + Stock.iRSI + " orderSize=" + orderSize + " price=" + Securities[Stock.Symbol].Close);
Log("BUY -> "+ Time.Date.ToShortDateString() + " " + Stock.Symbol + " " + price);
SetHoldings(Stock.Symbol, orderSize);
// MarketTicket = MarketOrder(Stock.Symbol, shares);
// LimitOrder(_symbol, quantity, (_price * 0.95m));
//var takeProfit = Stock.Close*tpPercent;
//LimitOrder(Stock.Symbol, 1 /*Stock.Quantity*/, price);
var stopLossPercentage = 7m/100m; // 7 Percent
orderSize = (int)Portfolio[Stock.Symbol].AbsoluteQuantity;
var stopPrice = Securities[Stock.Symbol].Low*(1.0m - stopLossPercentage);
StopLossTicket = StopMarketOrder(Stock.Symbol, - orderSize, stopPrice);
Debug("Submitted stop loss @ " + Time.Date.ToShortDateString() + " " + stopPrice.SmartRounding());
Log("Submitted stop loss @ " + Time.Date.ToShortDateString() + " " + stopPrice.SmartRounding());
}
if ( Portfolio[Stock.Symbol].Invested && Stock.Symbol == "eee")
{
// submit stop loss order for max loss on the trade
var stopLossPercentage = 0.03m;
orderSize = (int)Portfolio[Stock.Symbol].AbsoluteQuantity;
var stopPrice = Securities[Stock.Symbol].Low*(1 - stopLossPercentage);
StopLossTicket = StopMarketOrder(Stock.Symbol, - orderSize, stopPrice);
Log("Submitted stop loss @ " + stopPrice.SmartRounding());
}
if ( Portfolio[Stock.Symbol].Invested && Stock.iRSI > 60 )
{
Log("SELL >> " + Time.Date.ToShortDateString() + " " + Stock.Symbol + " price=" + price + " iRSI=" + Stock.iRSI );
Debug("Sell >> " + Time.Date.ToShortDateString() + " " + Stock.Symbol + " price=" + price + " iRSI=" + Stock.iRSI );
Liquidate(Stock.Symbol);
}
// sampledToday = data[Stock.Symbol].Time;
}
//sampledToday = data["SPY"].Time.Date;
} // end of OnData
public override void OnSecuritiesChanged(SecurityChanges changes)
{
sChanges = changes;
foreach (var removed in changes.RemovedSecurities)
{
SymbData.Remove(removed.Symbol);
// if (removed.Invested)
// {
// Liquidate(removed.Symbol);
// }
}
foreach (var added in changes.AddedSecurities)
{
if (!SymbData.ContainsKey(added.Symbol))
{
Add_SymbolData(added.Symbol);
Debug( " new--> Added: " + Time.Date.ToShortDateString() + " " + added.Symbol);
}
}
} // end of OnSecuritiesChanged
public void list_universe_menbers()
{
foreach (var universe in UniverseManager.Values) {
// User defined universe has symbols from AddSecurity/AddEquity calls
if (universe is UserDefinedUniverse) {
continue;
}
var symbols = universe.Members.Keys;
foreach (Symbol symbol in symbols) {
Debug(" -- actual symbol=" +symbol);
}
}
foreach (SecurityHolding x in Portfolio.Values){
Debug(" -- actual symbol in Portfolio=" + x.Symbol);
}
}
public bool search_universe_menbers (string SymName)
{
foreach (var universe in UniverseManager.Values) {
// User defined universe has symbols from AddSecurity/AddEquity calls
if (universe is UserDefinedUniverse) {
continue;
}
var symbols = universe.Members.Keys;
foreach (Symbol symbol in symbols) {
//Debug(" -- actual symbol=" +symbol);
if (symbol == SymName)
return true;
}
}
return false;
}
public void Add_SymbolData(string SymbolName)
{
var sma = SMA(SymbolName, lSMALen, Resolution.Daily); // Simple Moving Average
var rsi = RSI(SymbolName, rsiPeriods, MovingAverageType.Simple, Resolution.Daily);
var history = History(SymbolName, rsiPeriods, Resolution.Daily);
int count = history.Count();
// Debug (" History count=" + count + " " + Time.Date.ToShortDateString() + " added " + SymbolName);
foreach (var tradeBar in history) {
rsi.Update(tradeBar.EndTime, tradeBar.Close);
}
history = History(SymbolName, lSMALen, Resolution.Daily);
foreach (var tradeBar in history) {
sma.Update(tradeBar.EndTime, tradeBar.Close);
}
SymbData.Add(SymbolName, new SymbolData
{
Symbol = SymbolName,
hSMA = sma,
iRSI = rsi,
});
}
}
class SymbolData
{
public string Symbol;
public SimpleMovingAverage hSMA { get; set; }
public RelativeStrengthIndex iRSI { get; set; }
// Quick and dirty - store most recent close here
public SimpleMovingAverage Close { get; set; }
}
}