Overall Statistics
Total Trades
39
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
$39.00
Estimated Strategy Capacity
$3000000.00
Lowest Capacity Asset
AMZN R735QTJ8XC9X
namespace QuantConnect.Indicators {
	
	using System.Numerics;
	
	public class FourierSeries {
		
		private readonly int _period;
		private readonly decimal _frequency;
		private readonly int _depth;
		private decimal _leading;
		private decimal _value;
		
		public int WarmUpPeriod { get; }
		
		public bool IsReady => CosineCoefficients.Count() == _depth && SineCoefficients.Count() == _depth;
		public decimal Value => _value;
		
		public decimal LeadingCoefficient => _leading;
		public List<decimal> CosineCoefficients { get; }
		public List<decimal> SineCoefficients { get; }
		
		public void Reset()
		{
			CosineCoefficients.Clear();
			SineCoefficients.Clear();
		}
		
		public FourierSeries(string name, int period, decimal frequency = 2 * (decimal)Math.PI, int depth = 5) 
		{
			_period = period;
			_frequency = frequency;
			_depth = depth;
			
			WarmUpPeriod = period;
			CosineCoefficients = new List<decimal>();
			SineCoefficients = new List<decimal>();
		}
		
		public void Update(decimal value, decimal intercept, decimal slope) 
		{
			Console.WriteLine($"Updated");
			// calculate coefficients
			if(_leading == 0)
				_leading = ((slope * _frequency) + intercept);
				//_leading = 0;
			
			// clear coefficients
			CosineCoefficients.Clear();
			SineCoefficients.Clear();
			
			for(int i = 1; i <= _depth; i++) 
			{
				decimal a_n = (2 * slope * _frequency) / (decimal)(Math.Pow(i, 2) * Math.Pow(Math.PI, 2)) * ((decimal)Math.Pow(-1, i) - 1);
				CosineCoefficients.Add(a_n);
				
				SineCoefficients.Add(0.0m);
				/*
				decimal sin_n = (decimal)((Math.Sin(i * Math.PI) - Math.Sin(-i * Math.PI)) / (Math.PI * i));
				decimal cos_n = (decimal)((Math.Cos(i * Math.PI) - Math.Cos(-i * Math.PI)) / (Math.PI * i));
				
				decimal a_n = ((intercept - value) * sin_n) + (slope * (z / _frequency) * (decimal)Math.Sin((double)z)) - (slope * cos_n);
				CosineCoefficients.Add(a_n);
				
				decimal b_n = ((intercept - value) * cos_n) + (slope * (-z / _frequency) * (decimal)Math.Cos((double)z)) - (slope * sin_n);
				SineCoefficients.Add(b_n);
				*/
			}
			
			_value = CalculateFunction(value);
		}
		
		public decimal CalculateFunction(decimal value, int iterations) {
			
			decimal result = value;
			for(int i = 0; i <= iterations; i++)
				result = CalculateFunction(result);
			
			return result;
		}
		
		public decimal CalculateFunction(decimal value) {
			
			var function = LeadingCoefficient;
			
			for(int i = 0; i < _depth; i++) {
				function += (CosineCoefficients[i] * (decimal)Math.Cos((double)((i + 1) * (decimal)Math.PI * value / _frequency))) / (i + 1);
				function += (SineCoefficients[i] * (decimal)Math.Sin((double)((i + 1) * (decimal)Math.PI * value / _frequency))) / (i + 1);
			}
			
			return function;
		}
	}
}
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

using System;
using System.Linq;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra;

namespace QuantConnect.Indicators
{
    /// <summary>
    /// The Least Squares Moving Average (LSMA) first calculates a least squares regression line
    /// over the preceding time periods, and then projects it forward to the current period. In
    /// essence, it calculates what the value would be if the regression line continued.
    /// Source: https://rtmath.net/helpFinAnalysis/html/b3fab79c-f4b2-40fb-8709-fdba43cdb363.htm
    /// </summary>
    public class LeastSquaresMovingAverage : WindowIndicator<IndicatorDataPoint>, IIndicatorWarmUpPeriodProvider
    {
        /// <summary>
        /// Array representing the time.
        /// </summary>
        private readonly double[] _t;

        /// <summary>
        /// The point where the regression line crosses the y-axis (price-axis)
        /// </summary>
        public IndicatorBase<IndicatorDataPoint> Intercept { get; }
        
        /// <summary>
        /// The regression line slope
        /// </summary>
        public IndicatorBase<IndicatorDataPoint> Slope { get; }

        /// <summary>
        /// Required period, in data points, for the indicator to be ready and fully initialized.
        /// </summary>
        public int WarmUpPeriod => Period;

        /// <summary>
        /// Initializes a new instance of the <see cref="LeastSquaresMovingAverage"/> class.
        /// </summary>
        /// <param name="name">The name of this indicator</param>
        /// <param name="period">The number of data points to hold in the window</param>
        public LeastSquaresMovingAverage(string name, int period)
            : base(name, period)
        {
            _t = Vector<double>.Build.Dense(period, i => i + 1).ToArray();
            Intercept = new Identity(name + "_Intercept");
            Slope = new Identity(name + "_Slope");
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="LeastSquaresMovingAverage"/> class.
        /// </summary>
        /// <param name="period">The number of data points to hold in the window.</param>
        public LeastSquaresMovingAverage(int period)
            : this($"LSMA({period})", period)
        {
        }

        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="window"></param>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>
        /// A new value for this indicator
        /// </returns>
        protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint input)
        {
            // Until the window is ready, the indicator returns the input value.
            if (window.Samples <= window.Size) return input.Value;

            // Sort the window by time, convert the observations to double and transform it to an array
            var series = window
                .OrderBy(i => i.Time)
                .Select(i => Convert.ToDouble(i.Value))
                .ToArray();
            // Fit OLS
            var ols = Fit.Line(x: _t, y: series);
            Intercept.Update(input.Time, (decimal)ols.Item1);
            Slope.Update(input.Time, (decimal)ols.Item2);

            // Calculate the fitted value corresponding to the input
            return Intercept.Current.Value + Slope.Current.Value * Period;
        }

        /// <summary>
        /// Resets this indicator and all sub-indicators (Intercept, Slope)
        /// </summary>
        public override void Reset()
        {
            Intercept.Reset();
            Slope.Reset();
            base.Reset();
        }
    }
}
/*
	This program was developed by Quantify and is property of the client
    Usage and marketing of this program is permitted.
    
    Quantify Developer(s): Conor Flynn
    Date Created: 
    Client: 
    Client ID: 
    
    If you find a bug or an inconsistantcy please contact your assigned developer.
    Contact: cflynn@quantify-co.com
    
    To request a new copy of your program please contact support:
    Contact: support@quantify-co.com
    
    Note: Client ID is required for client verification upon requesting a new copy
*/

namespace QuantConnect.Algorithm.CSharp
{
	using System;
	using System.Numerics;
	
    public class ClientAlgorithm : QCAlgorithm
    {
    	// BACKTESTING PARAMETERS
    	// =================================================================================================================
    	
    	// general settings:
    	
    	// set starting cash
    	private int _startingCash = 100000;
    	
    	// backtesting start date time:
    	// date setting variables
    	private int _startYear = 2022;
    	private int _startMonth = 1;
    	private int _startDay = 3;
    	
    	// backtesting end date time:
    	// determines whether there is a specified end date
    	// if false it will go to the current date (if 'true' it will go to the specified date)
    	private bool _enableEndDate = true;
    	// date setting variables
    	private int _endYear = 2022;
    	private int _endMonth = 1;
    	private int _endDay = 3;
    	
    	// enable plotting
    	private bool enablePlotting = true;
    	
    	
    	// universe settings:
    	
    	// universe selection type
    	// determines whether securities are selected by QC's universe function
    	// or manually by the user
    	// manual = false; QC universe = true
    	private readonly bool _universeSelectionType = false;
    	
    	// number of securities for the universe selection to select
    	private readonly int _stockCount = 5;
    	
    	// use default values for universe
    	private readonly bool _useDefaultSymbolBase = false;
    	
    	// stock list for equities
    	// list of equities you want in the universe
    	// used in manual selection of universe
    	// set selectionType = false for activation
    	private readonly SymbolBase[] _universeList = new SymbolBase[]{
    			new SymbolBase(
    				"AMZN",				// symbol ticker
    				Resolution.Minute,	// data resolution
    				1,					// data resolution consolidation rate
    				1.0m				// portfolio allocation percentage
    			)
    	};
    	
    	// default symbol base settings
    	// used if using QC universe selection or a base is not detected for
    	// an added security
    	private readonly SymbolBase _defaultSymbolBase = new SymbolBase(
    		"<BASE>",					// do not modify
    		
    		// parameters to modify:
    		Resolution.Minute,			// data resolution
    		1,							// data resolution consolidation rate
    		1.0m						// portfolio allocation percentage
    	);
    	
    	
    	// position settings:
    	
    	// percent of portfolio to use for trading
    	// must be below 1
    	private readonly decimal _portfolioAllocation = 1m;
    	
    	// =================================================================================================================
		
		// contains all SymbolBase definitions
		private Dictionary<string, SymbolBase> _symbolBases = new Dictionary<string, SymbolBase>();
		
		// creates new universe variable setting
		private Dictionary<Symbol, SymbolData> _universe = new Dictionary<Symbol, SymbolData>();
		
		// security changes variable
		private SecurityChanges _securityChanges = SecurityChanges.None;
		
		// define offset universe to avoid first candle
		private bool offsetUniverse = true;
		
        public override void Initialize()
        {
        	// set start date
            SetStartDate(_startYear, _startMonth, _startDay);
            // set end date
            if(_enableEndDate)
            	SetEndDate(_endYear, _endMonth, _endDay);
            // set starting cash
            SetCash(_startingCash);
            
            // add default symbol base
            _symbolBases.Add("<BASE>", _defaultSymbolBase);
            
            // initialize universe
            if(!_universeSelectionType) {
 	            foreach(SymbolBase sb in _universeList) {
 	            	_symbolBases.Add(sb.Symbol, sb);
	            	AddEquity(sb.Symbol, sb.SymbolResolution);
	            }
            } else {
            	UniverseSettings.Resolution = _defaultSymbolBase.SymbolResolution;
            	AddUniverse(CoarseFilterFunction, FineFilterFunction
            	);
            }
        }

		// filter based on CoarseFundamental
	    public IEnumerable<Symbol> CoarseFilterFunction(IEnumerable<CoarseFundamental> coarse) {
	    	// returns the highest DollarVolume stocks
	    	// returns "totalNumberOfStocks" amount of stocks
	        return (from stock in coarse
	        		where !stock.HasFundamentalData
	        		orderby stock.DollarVolume descending
	        		select stock.Symbol).Take(_stockCount);
        	return Universe.Unchanged;
	    }
	    
	    // filters out all symbols not contained in the NASDAQ exchange
	    public IEnumerable<Symbol> FineFilterFunction(IEnumerable<FineFundamental> fine) {
	    	return (from stock in fine
	    			select stock.Symbol).Take(_stockCount);
	    }
		
		private decimal time = 0;
		public void OnDataConsolidated(object sender, TradeBar bar) {
			SymbolData sd = _universe[bar.Symbol];
			sd.Close.Add(bar.Close);
			
			if(!sd.Close.IsReady)
				return;
			
			if(!sd.IsReady) {
				sd.Fourier.Update(sd.Close[0], sd.LeastSquares.Intercept, sd.LeastSquares.Slope);
				return;
			}
			
			if(enablePlotting) {
				Plot("FS", "P", bar.Close);
				Plot("FS", "F", sd.Fourier.CalculateFunction(0));
				Plot("FS", "F1", ForwardEuler(sd.Fourier.CalculateFunction, sd.Close[1], 0, 1, 100).Last() / 2);
				Plot("FS", "F2", ForwardEuler(sd.Fourier.CalculateFunction, sd.Close[1], 0, 3, 100).Last() / 4);
				Plot("FS", "F3", ForwardEuler(sd.Fourier.CalculateFunction, sd.Close[1], 0, 5, 100).Last() / 6);
				Plot("LS", "I", sd.LeastSquares.Intercept);
				Plot("LS", "S", sd.LeastSquares.Slope);
				Plot("FSC", "A1+3/2", (sd.Fourier.CosineCoefficients[0] + sd.Fourier.CosineCoefficients[2]) / 2);
				Plot("FSS", "B1", sd.Fourier.SineCoefficients[0]);
				Plot("FSS", "B2", sd.Fourier.SineCoefficients[1]);
			}
			
			decimal coeff = (sd.Fourier.CosineCoefficients[0] + sd.Fourier.CosineCoefficients[2]) / 2;
			
			if(coeff < -3 && !Portfolio[sd.Symbol].Invested)
				SetHoldings(sd.Symbol, 1);
			else if(coeff > 3)
				Liquidate(sd.Symbol);
			
			sd.Fourier.Update(sd.Close[0], sd.LeastSquares.Intercept, sd.LeastSquares.Slope);
		}
		
		public decimal[] ForwardEuler(Func<decimal, decimal> f, decimal ya, int a, int b, int n) {
			
			decimal dt = (b - a * 1.0m) / n;
			
			decimal[] y = new decimal[n + 1];
			decimal[] t = new decimal[n + 1];
			y[0] = ya;
			t[0] = 0;
			
			for(int i = 1; i < n + 1; i++) {
				t[i] = t[i - 1] + dt;
				y[i] = y[i - 1] + (dt * f(t[i]));
			}
			
			return y;
		}
        
        // OnSecuritiesChanged runs when the universe updates current securities
        public override void OnSecuritiesChanged(SecurityChanges changes) {
            _securityChanges = changes;
            // remove stocks from list that get removed from universe
            foreach (var security in _securityChanges.RemovedSecurities) {
            	if(Securities[security.Symbol].Invested) {
            		Log($"{Time}->Portfolio: Liquidated security {security.Symbol} on universe exit");
            		Liquidate(security.Symbol);
            	}
            	
            	_universe.Remove(security.Symbol);
            	Log($"{Time}->Universe: Removed security {security.Symbol} from universe");
            }
            
            // add new securities to universe list
            foreach(var security in _securityChanges.AddedSecurities) {
            	// creare new SymbolData object
            	SymbolData sd;
            	
            	// if no base exists for symbol use default
            	if(!_symbolBases.ContainsKey(security.Symbol) || _useDefaultSymbolBase)
            		sd = new SymbolData(this, security.Symbol, _symbolBases["<BASE>"]);
            		
            	// otherwise use defined base
            	else
	            	sd = new SymbolData(this, security.Symbol, _symbolBases[security.Symbol]);
            	
            	// initialize consolidator and store if needed
            	TickConsolidator tickConsolidator = null;
            	TradeBarConsolidator barConsolidator = null;
            	if(sd.SymbolBase.SymbolResolution == Resolution.Tick) {
            		var consolidator = sd.GetTickConsolidator();
            		if(consolidator != null) {
	            		consolidator.DataConsolidated += OnDataConsolidated;
	            		SubscriptionManager.AddConsolidator(sd.Symbol, consolidator);
	            		tickConsolidator = consolidator;
            		}
            		
            	} else {
            		var consolidator = sd.GetConsolidator();
            		if(consolidator != null) {
	            		consolidator.DataConsolidated += OnDataConsolidated;
	            		SubscriptionManager.AddConsolidator(sd.Symbol, consolidator);
	            		barConsolidator = consolidator;
            		}
            	}
            	
            	// initialize indicators:
            	sd.Fourier = new FourierSeries(sd.Symbol, 15, 2 * (decimal)Math.PI, 100);
            	sd.LeastSquares = new LeastSquaresMovingAverage(sd.Symbol, 2);
            	
            	// register indicators
            	if(tickConsolidator != null) {
            		RegisterIndicator(sd.Symbol, sd.LeastSquares, tickConsolidator);
            	}
            	
            	else {
            		RegisterIndicator(sd.Symbol, sd.LeastSquares, barConsolidator);
            	}
            	
            	// load historical data
            	var historical = History(sd.Symbol, sd.LeastSquares.WarmUpPeriod, sd.SymbolBase.SymbolResolution);
            	foreach(var bar in historical) {
            		sd.LeastSquares.Update(bar.Time, bar.Close);
            	}
            	
            	// add SymbolData to universe
            	_universe.Add(security.Symbol, sd);
            	Log($"{Time}->Universe: Added security {security.Symbol} to universe");
            }
        }
        
        public class SymbolBase {
        	public readonly string Symbol;
        	public readonly Resolution SymbolResolution;
        	public readonly int SymbolConsolidationRate;
        	public readonly decimal PortfolioAllocation;
        	
        	public SymbolBase(string symbol = "<BASE>", Resolution symbolResolution = Resolution.Minute, int symbolConsolidationRate = 1, decimal portfolioAllocation = 1.0m) {
        		Symbol = symbol;
        		SymbolResolution = symbolResolution;
        		SymbolConsolidationRate = symbolConsolidationRate;
        		PortfolioAllocation = portfolioAllocation;
        	}
        }
		
		// default class containing all symbol information
		public class SymbolData {
			// Variables:
			// algorithm
			public readonly ClientAlgorithm Algorithm;
			// symbol
			public readonly string Symbol;
			// symbol base
			public readonly SymbolBase SymbolBase;
			// is ready
			public bool IsReady => Close.IsReady && Fourier.IsReady && LeastSquares.IsReady;
			
			// previous close
			public RollingWindow<decimal> Close = new RollingWindow<decimal>(10);
			// fourier series
			public FourierSeries Fourier;
			// least squares SMA
			public LeastSquaresMovingAverage LeastSquares;
			
			public SymbolData(ClientAlgorithm algorithm, Symbol symbol, SymbolBase symbolBase) {
				Algorithm = algorithm;
				Symbol = symbol;
				SymbolBase = symbolBase;
			}
			
			public TradeBarConsolidator GetConsolidator() {
				TimeSpan timeSpan;
				switch(SymbolBase.SymbolResolution) {
					case Resolution.Second:
						timeSpan = TimeSpan.FromSeconds(SymbolBase.SymbolConsolidationRate);
						break;
					case Resolution.Minute:
						timeSpan = TimeSpan.FromMinutes(SymbolBase.SymbolConsolidationRate);
						break;
					case Resolution.Hour:
						timeSpan = TimeSpan.FromHours(SymbolBase.SymbolConsolidationRate);
						break;
					case Resolution.Daily:
						timeSpan = TimeSpan.FromDays(SymbolBase.SymbolConsolidationRate);
						break;
					default:
						return null;
				}
				
				return new TradeBarConsolidator(timeSpan);
			}
			
			public TickConsolidator GetTickConsolidator() {
				return new TickConsolidator(SymbolBase.SymbolConsolidationRate);
			}
		}
    }
}