using System;
using System.Collections.Concurrent;
using System.Linq;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Indicators;
namespace QuantConnect.Algorithm.CSharp
{
public class AlertBlackViper : QCAlgorithm
{
private ConcurrentDictionary<Symbol, SelectionData> costats = new ConcurrentDictionary<Symbol, SelectionData>();
private class SelectionData
{
public RelativeStrengthIndex rsi;
public SimpleMovingAverage sRSI;
public ExponentialMovingAverage fast;
public ExponentialMovingAverage slow;
public IchimokuKinkoHyo ichi;
public long marketCap;
public decimal value;
public Int16 buy;
//Days since purchase
public SelectionData(QCAlgorithm algy, Symbol sym)
{
rsi = new RelativeStrengthIndex(14, MovingAverageType.Wilders);
sRSI = new SimpleMovingAverage(10);
fast = new ExponentialMovingAverage(50);
slow = new ExponentialMovingAverage(200);
ichi = new IchimokuKinkoHyo(9,26,52);
IEnumerable<TradeBar> bars = algy.History<TradeBar>(sym, 200);
foreach(TradeBar bar in bars)
{
Update(bar);
}
marketCap = 0;
value = 0;
buy = 0;
}
public bool Update(TradeBar tb)
{
int success = 0;
DateTime time = tb.EndTime;
value = tb.Close;
if(rsi.Update(time, value))
{
if(sRSI.Update(time, rsi))
{
success++;
}
}
// roll.Add(value);
fast.Update(time, value);
if(slow.Update(time, value))
{
success++;
}
if(ichi.Update(tb))
{
success++;
}
if(success == 3)
{
if
(
((sRSI.Current < 30m && ScaledDelta < 0) ||
(ichi.Tenkan > ichi.Kijun && ichi.Chikou > tb.Close
&& ichi.Kijun > ichi.SenkouA && ichi.Tenkan > ichi.SenkouB))
// && (marketCap == 0 || (marketCap > 1000000000L && marketCap < 5000000000L))
)
{
buy = 1;
}
else if
(
((sRSI.Current > 70m && ScaledDelta > 0) ||
(ichi.Tenkan < ichi.Kijun && ichi.Chikou < ichi.Kijun)
|| (ichi.Kijun < ichi.SenkouA && ichi.Tenkan < ichi.SenkouB))
)
{
buy = -1;
}
else buy = 0;
return true;
}
return false;;
}
public bool setMarketCap(long amt)
{
if(amt <= 0)
{
marketCap = 0;
}
else marketCap = amt;
return true;
}
public decimal ScaledDelta
{
get { return (fast - slow)/((fast + slow)/2m); }
}
public bool aboveOne
{
get { return value > fast || value > slow; }
}
}
public override void Initialize()
{
SetCash(1000);
UniverseSettings.Resolution = Resolution.Daily;
SetStartDate(2007, 1, 1);
SetEndDate(2010, 1, 1);
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash);
Portfolio.MarginCallModel = MarginCallModel.Null;
// AddUniverse(SelectCoarse, SelectFine);
AddSecurity(SecurityType.Equity, "SPY", Resolution.Daily);
SetBenchmark("SPY");
AddUniverse(SelectCoarse, SelectFine);
}
/// OnData event is the primary entry point for your algorithm.
// Each new data point will be pumped in here.
/// Slice object keyed by symbol containing the stock data
public void OnData(TradeBars tbs)
{
int amtStocks = 10;
if(IsWarmingUp)
return;
List<Symbol> data = (from s in tbs.Keys
let disun = costats.GetOrAdd(s, sym => new SelectionData(this, s))
let tb = tbs[s]
where disun.Update(tb) && disun.buy == 1
orderby disun.ScaledDelta ascending
select tb.Symbol).Take(amtStocks+10).ToList();
if(costats.ContainsKey("SPY"))
if(costats["SPY"].slow.IsReady)
if(costats["SPY"].aboveOne)
{
if(data.Count > 0)
{
decimal PPS = Portfolio.TotalPortfolioValue / amtStocks;
int total = (int)Math.Min(data.Count, Math.Floor(Portfolio.Cash / PPS));
int i = 0;
long count = 0;
Symbol sym = data[i];
decimal num = 0m;
if(total > 0)
while(count < total && i < total)
{
sym = data[i];
num = Math.Floor(PPS / tbs[sym].Close);
if(!Portfolio[sym].Invested && num > 0m)
{
MarketOrder(sym, num);
}
i++;
count++;
}
}
}
if (Portfolio.Invested)
{
foreach(Symbol item in Portfolio.Keys)
{
if(costats.ContainsKey(item))
{
SelectionData disun = costats[item];
if(Portfolio[item].Invested)
if(disun.buy == -1)
{
Liquidate(item);
}
}
}
}
}
public IEnumerable<Symbol> SelectCoarse(IEnumerable<CoarseFundamental> tbs)
{
return (from tb in tbs
select tb.Symbol);
}
public IEnumerable<Symbol> SelectFine(IEnumerable<FineFundamental> fine)
{
return (from f in fine
let disun = costats.GetOrAdd(f.Symbol, sym => new SelectionData(this, f.Symbol))
where disun.setMarketCap(f.MarketCap)
select f.Symbol);
}
}
}