using System;
using System.Linq;
using QuantConnect.Indicators;
using QuantConnect.Models;
using MathNet.Numerics.Statistics;
namespace QuantConnect
{
// https://www.quantconnect.com/tutorials/dynamic-breakout-ii-strategy/
public class DynamicBreakoutAlgorithm : QCAlgorithm
{
IEnumerable<Slice> slices;
IEnumerable<decimal> close;
IEnumerable<decimal> high;
IEnumerable<decimal> low;
BollingerBands Bolband;
private const string Symbol = "BTCUSD";
//private const string Symbol = "GBPUSD";
private int numdays = 20;
private decimal buypoint, sellpoint, longLiqPoint, shortLiqPoint, yesterdayclose = 0;
public override void Initialize()
{
SetStartDate(2010,1,15);
SetEndDate(2016,2,15);
SetCash(100000);
AddCrypto(Symbol, Resolution.Hour);
SetBenchmark(Symbol);
const int ceiling = 60, floor = 20;
double[] closes, highs, lows, historyclose;
double todayvol, yesterdayvol, deltavol;
Schedule.On(DateRules.EveryDay(Symbol), TimeRules.BeforeMarketClose(Symbol, 1), () =>
{
slices = History(31, Resolution.Daily);
close = slices.Get(Symbol, Field.Close);
closes = close.ToDoubleArray();
todayvol = closes.Skip(1).StandardDeviation();
yesterdayvol = closes.Take(30).StandardDeviation();
deltavol = (todayvol - yesterdayvol) / todayvol;
numdays = (int)(Math.Round(numdays * (1 + deltavol)));
numdays = Math.Max(Math.Min(numdays, ceiling), floor);
Bolband = BB(Symbol, numdays, 2, MovingAverageType.Simple, Resolution.Daily);
slices = History(numdays, Resolution.Daily);
high = slices.Get(Symbol, Field.High);
highs = high.ToDoubleArray();
low = slices.Get(Symbol, Field.Low);
lows = low.ToDoubleArray();
buypoint = (decimal)highs.Max();
sellpoint = (decimal)lows.Min();
close = slices.Get(Symbol, Field.Close);
historyclose = close.ToDoubleArray();
longLiqPoint = (decimal)(historyclose.Mean());
shortLiqPoint = (decimal)(historyclose.Mean());
yesterdayclose = (decimal)historyclose.Skip(numdays-2).Take(1).Mean();
});
}
private decimal price, holdings;
public void OnData(TradeBars data)
{
// wait for our BollingerBand to fully initialize
if (yesterdayclose == 0)
{
return;
}
holdings = Portfolio[Symbol].Quantity;
price = Portfolio[Symbol].Price;
if (yesterdayclose > Bolband.UpperBand.Current.Value && price >= buypoint)
{
SetHoldings(Symbol, 1);
}
else if (yesterdayclose < Bolband.LowerBand.Current.Value && price <= sellpoint)
{
SetHoldings(Symbol, -1);
}
if (holdings > 0 && price <= longLiqPoint)
{
Liquidate(Symbol);
}
else if (holdings < 0 && price >= shortLiqPoint)
{
Liquidate(Symbol);
}
Log(yesterdayclose + " # of day " + numdays);
}
}
}