| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
using QuantConnect.Indicators.CandlestickPatterns;
namespace QuantConnect.Algorithm.CSharp
{
public partial class TestAlgo : QCAlgorithm
{
//****************************************************************************************************************************************
// INITIALIASE BLOCK
//****************************************************************************************************************************************
public override void Initialize()
{
SetStartDate(2019, 10, 12);
SetEndDate(2020, 01, 20);
SetAccountCurrency("USD");
SetCash(100000);
// Loop through our list of symbols and add them to our subscription manager
foreach (var _symbol in _MySymbolList)
{
var _Crypto = AddCrypto(_symbol, _Res);
DataDico.Add(_symbol, new SymbolData(this, _Crypto.Symbol, _Crypto.BaseCurrencySymbol));
}
SetWarmUp(TimeSpan.FromDays(_WarmUpPeriod));
SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
}
//****************************************************************************************************************************************
// ONDATA BLOCK
//****************************************************************************************************************************************
public override void OnData(Slice data)
{
//Loop through our dictionary
foreach (var symbolData in DataDico.Values)
{
if(!data.ContainsKey(symbolData.Symbol)) { return; }
//Check if algorithm is warming up and if indicators are ready, if not break
if(IsWarmingUp) { return; }
if(!symbolData.IsReady()) { return; }
if(!symbolData.ConsolidatorFlag) { return; }
symbolData.ConsolidatorFlag = false;
symbolData.Price = data[symbolData.Symbol].Close;
Plot($"BB ext {symbolData.Symbol}", $"Price", symbolData.Price);
Plot($"BB ext {symbolData.Symbol}", $"Upper Band", symbolData.BBext.UpperBand);
Plot($"BB ext {symbolData.Symbol}", $"Middle Band", symbolData.BBext.MiddleBand);
Plot($"BB ext {symbolData.Symbol}", $"Lower Band", symbolData.BBext.LowerBand);
Plot($"BB ext BandWidth {symbolData.Symbol}", $"BandWidth Indic", symbolData.BBext.BandWidth);
Plot($"BB ext BandWidth {symbolData.Symbol}", $"BandWidth Calc", ((symbolData.BBext.UpperBand - symbolData.BBext.LowerBand) / symbolData.BBext.MiddleBand)); // * 100m);
Plot($"%B {symbolData.Symbol}", $"%B Indic", symbolData.BBext.PctB);
Plot($"%B {symbolData.Symbol}", $"%B Calc", (symbolData.Price - symbolData.BBext.LowerBand) / (symbolData.BBext.UpperBand - symbolData.BBext.LowerBand));
}
}
}
}namespace QuantConnect.Algorithm.CSharp
{
public partial class TestAlgo : QCAlgorithm
{
//****************************************************************************************************************************************
//USER VARIABLES
//****************************************************************************************************************************************
Resolution _Res = Resolution.Hour; // Reference resolution for our custom TradeBar
// Set the size of our rolling window (used among other to store historical consolidated bars)
private int _WarmUpPeriod = 200;
public decimal _PctRisk = 0.10m;
private decimal _StopLossPct = 0.05m;
//***Symbol List***
Dictionary <string, SymbolData> DataDico = new Dictionary <string, SymbolData>();
List <string> _MySymbolList = new List <string>
{
//"BTCUSD",
"ETHUSD",
//"LTCUSD",
//"BCHUSD"
};
private decimal _TotalEquity;
}
}namespace QuantConnect.Algorithm.CSharp
{
public partial class TestAlgo : QCAlgorithm
{
public class SymbolData
{
public readonly QCAlgorithm algorithm;
public readonly Symbol Symbol;
public readonly string BaseSymbol;
public readonly string AccountSymbol;
public OrderTicket EntryOrder;
public OrderTicket StopMarketOrder;
public decimal EntryPrice;
public decimal StopPrice;
public readonly TimeSpan BarPeriod;
public bool ConsolidatorFlag = false; // Flag whether a new custom candle has been fully consolidated; used to prevent ONDATA block code to be executed otherwise
public readonly RollingWindow<IBaseDataBar> BarsWin;
public TradeBarConsolidator Consolidator;
public static int _BarPerTimeSpan = 24; // Number of block of data per custum TradeBar
public readonly TimeSpan _BarPeriod = TimeSpan.FromHours(_BarPerTimeSpan); // Set the size of our custum TradeBar
public readonly int _WindowSize = 2;
public decimal Holding;
public decimal Price;
public decimal Price_P1;
//***Bollinger Bands***
public BollingerBandsExtended BBext;
public BollingerBands BBofBB;
private int _BBPeriod = 14;
private decimal _BBxStdv = 2.5m;
private MovingAverageType _BB_MAtype = MovingAverageType.Simple;
private int _BBofBBPeriod = 20;
private decimal _BBofBBxStdv = 2.0m;
//***SymbolData class constructor which initializes a new instance of SymbolData***
public SymbolData(QCAlgorithm algorithm, Symbol symbol, string baseSymbol)
{
this.algorithm = algorithm;
Symbol = symbol;
BaseSymbol = baseSymbol;
AccountSymbol = symbol.ToString().Remove(0,3);
Consolidator = new TradeBarConsolidator(_BarPeriod);
BarsWin = new RollingWindow<IBaseDataBar>(_WindowSize);
BBext = new BollingerBandsExtended(Symbol, _BBPeriod, _BBxStdv, _BB_MAtype);
//BBofBB = new BollingerBandsExtended(_BBofBBPeriod, _BBofBBxStdv).Of(BBext.PctB);
Consolidator.DataConsolidated += (sender, baseData) =>
{
// '_bar' here is our newly consolidated data
var _bar = (IBaseDataBar)baseData;
// Update the indicators
ConsolidatorFlag = true;
BarsWin.Add(_bar);
BBext.Update(_bar.Time, _bar.Close);
//BBofBB.Update(_bar.Time, _bar.Close);
};
algorithm.SubscriptionManager.AddConsolidator(symbol, Consolidator); // Adding this consolidator to the Subscription Manager so it gets auto updates
}
//***Returns true if all the data in this instance is ready (indicators, rolling windows, ect...)***
public bool IsReady()
{
return BarsWin.IsReady && BBext.IsReady;
}
}
}
}namespace QuantConnect
{
/// <summary>
/// This indicator creates a moving average (middle band) with an upper band and lower band
/// fixed at k standard deviations above and below the moving average.
/// </summary>
public class BollingerBandsExtended : Indicator, IIndicatorWarmUpPeriodProvider
{
//public IndicatorDataPoint price; // { get; private set; }
public SimpleMovingAverage smaPrice { get; private set; }
/// <summary>
/// Gets the type of moving average
/// </summary>
public MovingAverageType MovingAverageType { get; private set; }
/// <summary>
/// Gets the standard deviation
/// </summary>
public IndicatorBase<IndicatorDataPoint> StandardDeviation { get; private set; }
/// <summary>
/// Gets the middle Bollinger band (moving average)
/// </summary>
public IndicatorBase<IndicatorDataPoint> MiddleBand { get; private set; }
/// <summary>
/// Gets the upper Bollinger band (middleBand + k * stdDev)
/// </summary>
public IndicatorBase<IndicatorDataPoint> UpperBand { get; private set; }
/// <summary>
/// Gets the lower Bollinger band (middleBand - k * stdDev)
/// </summary>
public IndicatorBase<IndicatorDataPoint> LowerBand { get; private set; }
/// <summary>
/// Gets the Bollinger Band Width ((Upper Band - Lower Band) / Middle Band) * 100
/// </summary>
public IndicatorBase<IndicatorDataPoint> BandWidth { get; private set; }
/// <summary>
/// Gets the Bollinger %B (Price - Lower Band)/(Upper Band - Lower Band)
/// </summary>
public IndicatorBase<IndicatorDataPoint> PctB { get; private set; }
/// <summary>
/// Initializes a new instance of the BollingerBands class
/// </summary>
/// <param name="period">The period of the standard deviation and moving average (middle band)</param>
/// <param name="k">The number of standard deviations specifying the distance between the middle band and upper or lower bands</param>
/// <param name="movingAverageType">The type of moving average to be used</param>
public BollingerBandsExtended(int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple)
: this($"BB({period},{k})", period, k, movingAverageType)
{
}
/// <summary>
/// Initializes a new instance of the BollingerBands class
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="period">The period of the standard deviation and moving average (middle band)</param>
/// <param name="k">The number of standard deviations specifying the distance between the middle band and upper or lower bands</param>
/// <param name="movingAverageType">The type of moving average to be used</param>
public BollingerBandsExtended(string name, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple)
: base(name)
{
/*price = new FunctionalIndicator<IBaseDataBar>(name + "_Price",
currentBar =>
{
var value = UpdatePrice(currentBar);
return value;
},
isReady => price != null
); */
WarmUpPeriod = period;
MovingAverageType = movingAverageType;
smaPrice = new SimpleMovingAverage(name + "_smaPrice", 1);
StandardDeviation = new StandardDeviation(name + "_StandardDeviation", period);
MiddleBand = movingAverageType.AsIndicator(name + "_MiddleBand", period);
LowerBand = MiddleBand.Minus(StandardDeviation.Times(k), name + "_LowerBand");
UpperBand = MiddleBand.Plus(StandardDeviation.Times(k), name + "_UpperBand");
BandWidth = UpperBand.Minus(LowerBand).Over(MiddleBand, name + "_BandWidth"); //BandWidth = (UpperBand.Minus(LowerBand).Over(MiddleBand).Times(100m, name + "_BandWidth");
PctB = smaPrice.Minus(LowerBand).Over(UpperBand.Minus(LowerBand), name + "_PctB");
//PctB = price.Minus(LowerBand).Over(UpperBand.Minus(LowerBand), name + "_PctB");
//PctB = (price - LowerBand) / (UpperBand - LowerBand);
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady => MiddleBand.IsReady && UpperBand.IsReady && LowerBand.IsReady;
/// <summary>
/// Required period, in data points, for the indicator to be ready and fully initialized.
/// </summary>
public int WarmUpPeriod { get; }
/// <summary>
/// Computes the next value of the following sub-indicators from the given state:
/// StandardDeviation, MiddleBand, UpperBand, LowerBand
/// </summary>
/// <param name="input">The input given to the indicator</param>
/// <returns>The input is returned unmodified.</returns>
protected override decimal ComputeNextValue(IndicatorDataPoint input)
{
StandardDeviation.Update(input);
MiddleBand.Update(input);
smaPrice.Update(input);
//UpdatePrice(input);
//price = input;
return input;
}
/// <summary>
/// Resets this indicator and all sub-indicators (StandardDeviation, LowerBand, MiddleBand, UpperBand)
/// </summary>
public override void Reset()
{
StandardDeviation.Reset();
MiddleBand.Reset();
UpperBand.Reset();
LowerBand.Reset();
BandWidth.Reset();
PctB.Reset();
base.Reset();
}
private decimal UpdatePrice(IBaseDataBar input)
{
var _price = new decimal(0.0);
_price = input.Close;
return _price;
}
}
}