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($"BB ext BandWidth {symbolData.Symbol}", $"Upper Band", symbolData.BBofBB.UpperBand);
				Plot($"BB ext BandWidth {symbolData.Symbol}", $"Middle Band", symbolData.BBofBB.MiddleBand);
				Plot($"BB ext BandWidth {symbolData.Symbol}", $"Lower Band", symbolData.BBofBB.LowerBand);
				
				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 BollingerBands(_BBofBBPeriod, _BBofBBxStdv).Of(BBext.BandWidth);

	    		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; }
        public decimal price { 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 = IndicatorExtensions.Times(UpperBand.Minus(LowerBand).Over(MiddleBand, name + "_BandWidth"), 100);	//BandWidth = (UpperBand.Minus(LowerBand).Over(MiddleBand).Times(100m, name + "_BandWidth");
            PctB = smaPrice.Minus(LowerBand).Over(UpperBand.Minus(LowerBand), name + "_PctB");
            //PctB = priceWin[0].Minus(LowerBand).Over(UpperBand.Minus(LowerBand), name + "_PctB");
            //PctB = (priceWin[0] - LowerBand) / (UpperBand - LowerBand);
            //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();
            smaPrice.Reset();
            base.Reset();
        }
        
        private decimal UpdatePrice(IBaseDataBar input)
        {
            var _price = new decimal(0.0);

            _price = input.Close;

            return _price;
        }
    }
}