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, 12, 12);
            SetEndDate(2020, 01, 13);
			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(_Crypto.Symbol, _Crypto.BaseCurrencySymbol, _BarPeriod, _WindowSize));
            }
            
            // Loop through the dictionary
            foreach (var kvp in DataDico)
            {
            	var symbolData = kvp.Value;
	            var Consolidator = new TradeBarConsolidator(_BarPeriod);
	            
        		///symbolData.W_Bottom = new WBottom(_Wbottom_Period, _Wbottom_MinBarInterval);	// UNCOMMENT THIS LINES AND IT WILL BREAK
        		///RegisterIndicator(symbolData.Symbol, symbolData.W_Bottom, Consolidator); 	// UNCOMMENT THIS LINES AND IT WILL BREAK

				Consolidator.DataConsolidated += (sender, baseData) =>
				{
					// '_bar' here is our newly consolidated data
        			var _bar = (IBaseDataBar)baseData;
        			
        	        // Update the indicators
        			symbolData.ConsolidatorFlag = true;
        			symbolData.BarsWin.Add(_bar);
        			///symbolData.W_Bottom.wBottom.BarsWin.Add(_bar);							// UNCOMMENT THIS LINES AND IT WILL BREAK

				};
				
            	Consolidator.DataConsolidated += ConsolidatorHandler;						// Call ConsolidatorHandeler custom method
            	SubscriptionManager.AddConsolidator(symbolData.Symbol, Consolidator);		// Adding this consolidator to the Subscription Manager so it gets auto updates
            }

            SetWarmUp(TimeSpan.FromDays(_WarmUpPeriod));
            SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin);
            
        }
        
        private void ConsolidatorHandler(object sender, IBaseDataBar _Consolidated)
        {
        	// This method will be called every time a new consolidated bar is ready
        	//Log($"{_Consolidated.EndTime:o} {_BarPerTimeSpan}-hour bar consolidated.");
        }
        
        
		//****************************************************************************************************************************************
        // 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;
				

				//Log($"O: {data[symbolData.Symbol].Open}, H: {data[symbolData.Symbol].High}, L: {data[symbolData.Symbol].Low}, C: {data[symbolData.Symbol].Close}");
				//Plot($"W Bottom {symbolData.Symbol}",$"W Bottom({_Wbottom_Period})", symbolData.W_Bottom);
				//Log($"W Bottom | B_Low01 = {symbolData.W_Bottom.wBottom.B_Low01value}");

        	}
        }

    }
}
namespace QuantConnect.Algorithm.CSharp
{
	public partial class TestAlgo : QCAlgorithm
	{
		//****************************************************************************************************************************************
		//USER VARIABLES
		//****************************************************************************************************************************************
		
    	Resolution _Res = Resolution.Hour;												// Reference resolution for our custom TradeBar
    	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;											// 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;
		private int _Wbottom_Period = 20;
		private int _Wbottom_MinBarInterval = 3;
		
    	//***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 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 decimal Holding;
	     	public decimal Price;
	    	public decimal Price_P1;

			//***Indicator declaration***
	    	///public WBottom W_Bottom;
	
	    	//***SymbolData class constructor which initializes a new instance of SymbolData***
	    	public SymbolData(Symbol symbol, string baseSymbol, TimeSpan barPeriod, int _windowSize)
	    	{
	    		Symbol = symbol;
	    		BaseSymbol = baseSymbol;
	    		AccountSymbol = symbol.ToString().Remove(0,3);
	    		BarPeriod = barPeriod;
	    		BarsWin = new RollingWindow<IBaseDataBar>(_windowSize);
	    	}
	    		
	    	//***Returns true if all the data in this instance is ready (indicators, rolling windows, ect...)***
	    	public bool IsReady
	    	{
	    		get {return true;} //W_Bottom.IsReady;}
	    	}
	    }
	}
}
using System.Linq;

namespace QuantConnect
{

    /// <summary>
    /// Indicator that keeps track of the daily running volume
    /// </summary>
    public class WBottom : BarIndicator, IIndicatorWarmUpPeriodProvider
    {
        public WBottomClass wBottom;
        private int wBottomFlag = 0; // W Bottom Flag: 0 = false / 1 = true

        /// Gets a flag indicating when this indicator is ready and fully initialized
        public override bool IsReady => wBottom.IsReady;

		/// Required period, in data points, for the indicator to be ready and fully initialized.
		public int WarmUpPeriod { get; }

        /// Initializes a new instance of the "WBottom" class
        public WBottom(int period, int interval = 3)
            : this($"WBottom({period})", period, interval)
        {
        }

        /// Initializes a new instance of the "WBottom" class
        /// <param name="name">The name of this indicaor</param>
        public WBottom(string name, int period, int interval)
            : base(name)
        {
        	wBottom = new WBottomClass(period, interval);
            WarmUpPeriod = 1 + period;
        }

        /// Computes the next value of this indicator from the given state
        /// "input" = The input given to the indicator
        /// Returns a new value for this indicator
        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
	        //wBottom.BarsWin.Update(input);
	        
	        ///Step 1: Identify first Low (B)
            wBottom.B_Low01value = wBottom.BarsWin[wBottom._Period/2 -1].Low;
            wBottom.B_Low01index = wBottom._Period/2 -1;
            
            for(int i = wBottom.B_Low01index; i <= wBottom._Period -1 ; i++)
            {
            	decimal number = wBottom.BarsWin[i].Low;
            	if(number < wBottom.B_Low01value)
            	{
            		wBottom.B_Low01value = number;
            		wBottom.B_Low01index = i;
            	}
            }

	        ///Step 2: Identify second Low (D)
            wBottom.D_Low02value = wBottom.BarsWin[0].Low;
            wBottom.D_Low02index = 0;
            
            for(int i = 0; i < wBottom.B_Low01index - wBottom._Interval ; i++)
            {
            	decimal number = wBottom.BarsWin[i].Low;
            	if(number < wBottom.D_Low02value)
            	{
            		wBottom.D_Low02value = number;
            		wBottom.D_Low02index = i;
            	}
            }

	        ///Step 3: Identify first High (A)
            wBottom.A_High01value = wBottom.BarsWin[wBottom.B_Low01index +1].High;
            wBottom.A_High01index = wBottom.B_Low01index +1;
            
            for(int i = wBottom.A_High01index; i <= wBottom._Period -1 ; i++)
            {
            	decimal number = wBottom.BarsWin[i].High;
            	if(number > wBottom.A_High01value)
            	{
            		wBottom.A_High01value = number;
            		wBottom.A_High01index = i;
            	}
            }

	        ///Step 4: Identify second High (C)
            wBottom.C_High02value = wBottom.BarsWin[wBottom.D_Low02index +1].High;
            wBottom.C_High02index = wBottom.D_Low02index +1;
            
            for(int i = wBottom.C_High02index; i <= wBottom.B_Low01index -1 ; i++)
            {
            	decimal number = wBottom.BarsWin[i].High;
            	if(number > wBottom.C_High02value)
            	{
            		wBottom.C_High02value = number;
            		wBottom.C_High02index = i;
            	}
            }

	        ///Step 5: Identify third High (E)
            wBottom.E_High03value = wBottom.BarsWin[0].High;
            wBottom.E_High03index = 0;
            
            for(int i = 0; i <= wBottom.D_Low02index -1 ; i++)
            {
            	decimal number = wBottom.BarsWin[i].High;
            	if(number > wBottom.E_High03value)
            	{
            		wBottom.E_High03value = number;
            		wBottom.E_High03index = i;
            	}
            }
            
            if(wBottom.B_Low01index - wBottom.A_High01index <= wBottom._Interval
            || wBottom.C_High02index - wBottom.B_Low01index <= wBottom._Interval
            || wBottom.D_Low02index - wBottom.C_High02index <= wBottom._Interval
            || wBottom.E_High03index - wBottom.D_Low02index <= wBottom._Interval)
            {wBottomFlag = 0;} else {wBottomFlag = 1;}

            return wBottomFlag;

        }

        
        public class WBottomClass
        {
        	public int _Period;
        	public int _Interval;
        	public decimal A_High01value;
            public decimal C_High02value;
            public decimal E_High03value;
            public decimal B_Low01value;
            public decimal D_Low02value;
        	public int A_High01index;
            public int C_High02index;
            public int E_High03index;
            public int B_Low01index;
            public int D_Low02index;
            public readonly RollingWindow<IBaseDataBar> BarsWin;
            
    		//***WBottomClass constructor which initializes a new instance of the class***
    		public WBottomClass(int period, int interval)
    		{
    			BarsWin = new RollingWindow<IBaseDataBar>(period);
    			_Period = period;
    			_Interval = interval;
    		}
    		
    		public bool IsReady
    		{
    			get {return BarsWin.IsReady;}
    		}
        }
    }
}