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); } } } }