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); //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(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;
				
				//Debug($"RollingWindow: {symbolData.BarsWin[0]}, {symbolData.BarsWin[1]}");
				Debug($"W Bottom | B_Low01 = {symbolData.W_Bottom.wBottom.B_Low01value} || W Bottom Flag: {symbolData.W_Bottom}");

				

        	}
        }

    }
}
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 int _Wbottom_Period = 20;
			public int _Wbottom_MinBarInterval = 3;
			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 WBottom W_Bottom;
			
	   		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(QCAlgorithm algorithm, Symbol symbol, string baseSymbol)
	    	{	
	    		this.algorithm = algorithm;
	    		Symbol = symbol;
	    		BaseSymbol = baseSymbol;
	    		AccountSymbol = symbol.ToString().Remove(0,3);
	    		
	    		BarsWin = new RollingWindow<IBaseDataBar>(_WindowSize);
	    		W_Bottom = new WBottom(_Wbottom_Period, _Wbottom_MinBarInterval);
	    		Consolidator = new TradeBarConsolidator(_BarPeriod);
	    		
	    		Consolidator.DataConsolidated += (sender, baseData) =>
				{
					// '_bar' here is our newly consolidated data
        			var _bar = (IBaseDataBar)baseData;
        	        // Update the indicators
        			ConsolidatorFlag = true;
        			BarsWin.Add(_bar);
        			W_Bottom.Update(_bar);
        										

				};
				
						// Call ConsolidatorHandeler custom method
            	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; //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.Add(input);
	        
	        if(!wBottom.BarsWin.IsReady){
	        	return wBottomFlag;
	        }
	        ///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 - 2 ; 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_High01index = wBottom.B_Low01index +1;
	        wBottom.A_High01value = wBottom.BarsWin[wBottom.B_Low01index +1].High;
	        
            
            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_High02index = wBottom.D_Low02index +1;
			wBottom.C_High02value = wBottom.BarsWin[wBottom.D_Low02index +1].High;
            
            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;}
    		}
        }
    }
}