Overall Statistics |
Total Trades 493 Average Win 1.52% Average Loss -1.14% Compounding Annual Return 5.116% Drawdown 25.000% Expectancy 0.177 Net Profit 56.826% Sharpe Ratio 0.438 Loss Rate 49% Win Rate 51% Profit-Loss Ratio 1.33 Alpha 0.047 Beta 0.589 Annual Standard Deviation 0.133 Annual Variance 0.018 Information Ratio 0.289 Tracking Error 0.133 Treynor Ratio 0.099 Total Fees $4408.91 |
namespace QuantConnect.Algorithm.CSharp { /// <summary> /// Basic template algorithm simply initializes the date range and cash. This is a skeleton /// framework you can use for designing an algorithm. /// </summary> public class BasicTemplateAlgorithm : QCAlgorithm { private Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA); SlopeIndicator _hislope; SlopeIndicator _loslope; /// <summary> /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. /// </summary> public override void Initialize() { SetStartDate(2008, 10, 07); //Set Start Date SetEndDate(2017, 10, 11); //Set End Date SetCash(100000); //Set Strategy Cash // Find more symbols here: http://quantconnect.com/data // Forex, CFD, Equities Resolutions: Tick, Second, Minute, Hour, Daily. // Futures Resolution: Tick, Second, Minute // Options Resolution: Minute Only. AddEquity("SPY", Resolution.Minute); _hislope = new SlopeIndicator(_spy, 30, true, 1e-8); _loslope = new SlopeIndicator(_spy, 30, false, 1e-8); var consolidator = new TradeBarConsolidator(new TimeSpan(0, 15, 0)); RegisterIndicator(_spy, _hislope, consolidator, Field.High); RegisterIndicator(_spy, _loslope, consolidator, Field.Low); // There are other assets with similar methods. See "Selecting Options" etc for more details. // AddFuture, AddForex, AddCfd, AddOption } /// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">Slice object keyed by symbol containing the stock data</param> public override void OnData(Slice data) { if(!_hislope.IsReady) { return; } var hiangle = Math.Atan((double)_hislope.Current.Value) * (180/Math.PI); var loangle = Math.Atan((double)_loslope.Current.Value) * (180/Math.PI); if (!Portfolio.Invested && ((hiangle<-10 && loangle>10) || loangle>20)) { SetHoldings(_spy, 10); Debug(string.Format("Purchased Stock {0} {1}",hiangle,loangle)); } else if (Portfolio.Invested && loangle<2) { Liquidate(_spy); Debug(string.Format("Liquidated Stock {0} {1}",hiangle,loangle)); } } } }
using System; using System.Collections.Generic; namespace QuantConnect { public class HHLL { public static List<int> PeakinessTest(decimal[] histogram, double peakinessThres) { int j = 0; int length = histogram.Length; List<int> valleys = new List<int>(); List<int> peaks = new List<int>(); List<decimal> values = new List<decimal>(); List<decimal> levels = new List<decimal>(); //The start of the valley decimal vA = histogram[j]; decimal P = vA; //The end of the valley decimal vB = 0; //The width of the valley, default width is 1 int W = 1; //The sum of the pixels between vA and vB decimal N = 0; //The measure of the peaks peakiness double peakiness = 0.0; int peak = 0; bool l = false; decimal level = 0; try { level = histogram[0]; while (j < length-1) { l = false; vA = histogram[j]; P = vA; W = 1; N = vA; int i = j + 1; //To find the peak while (i < histogram.Length - 1 && P < histogram[i]) { P = histogram[i]; W++; N += histogram[i]; i++; levels.Add(level); } //To find the border of the valley other side peak = i - 1; vB = histogram[i]; N += histogram[i]; i++; W++; levels.Add(level); l = true; while( i < histogram.Length - 1 && vB >= histogram[i]) { vB = histogram[i]; W++; N += histogram[i]; i++; levels.Add(level); } //Calculate peakiness peakiness = (1 - (double)((vA + vB) / ((decimal)2.0 * P))) * (1 - ((double)N / (double)(W * P))); if (peakiness > peakinessThres & !valleys.Contains(j)) { values.Add(histogram[j]); peaks.Add(peak); valleys.Add(j); valleys.Add(i - 1); level = histogram[j]; } j = i - 1; } } catch (Exception e) { if (l) { vB = histogram[length-1]; peakiness = (1 - (double)((vA + vB) / ((decimal)2.0 * P))) * (1 - ((double)N / (double)(W * P))); if (peakiness > peakinessThres) valleys.Add(length); //peaks.Add(255); //return valleys; return peaks; } } //if(!valleys.Contains(255)) // valleys.Add(255); //Console.WriteLine(string.Join(",", peaks.ToArray())); // Console.WriteLine(string.Join(",", values.ToArray())); // Console.WriteLine(string.Join(",", levels.ToArray())); //return valleys; return peaks; } public static List<int> ValleysTest(decimal[] histogram, double peakinessThres) { int j = 0; int length = histogram.Length; List<int> valleys = new List<int>(); List<int> peaks = new List<int>(); List<decimal> values = new List<decimal>(); List<decimal> levels = new List<decimal>(); //The start of the valley decimal vA = histogram[j]; decimal P = vA; //The end of the valley decimal vB = 0; //The width of the valley, default width is 1 int W = 1; //The sum of the pixels between vA and vB decimal N = 0; //The measure of the peaks peakiness double peakiness = 0.0; int peak = 0; bool l = false; decimal level = 0; try { level = histogram[0]; while (j < length -1) { l = false; vA = histogram[j]; P = vA; W = 1; N = vA; int i = j + 1; //To find the peak while (i < histogram.Length - 1 && P < histogram[i]) { P = histogram[i]; W++; N += histogram[i]; i++; levels.Add(level); } //To find the border of the valley other side peak = i - 1; vB = histogram[i]; N += histogram[i]; i++; W++; levels.Add(level); l = true; while (i < histogram.Length - 1 && vB >= histogram[i]) { vB = histogram[i]; W++; N += histogram[i]; i++; levels.Add(level); } //Calculate peakiness peakiness = (1 - (double)((vA + vB) / ((decimal)2.0 * P))) * (1 - ((double)N / (double)(W * P))); if (peakiness > peakinessThres & !valleys.Contains(j)) { values.Add(histogram[j]); peaks.Add(peak); valleys.Add(j); valleys.Add(i - 1); level = histogram[j]; } j = i - 1; } } catch (Exception e) { if (l) { vB = histogram[length-1]; peakiness = (1 - (double)((vA + vB) / ((decimal)2.0 * P))) * (1 - ((double)N / (double)(W * P))); if (peakiness > peakinessThres) valleys.Add(length); //peaks.Add(255); //return valleys; return valleys; } } //if(!valleys.Contains(255)) // valleys.Add(255); // Console.WriteLine(string.Join(",", peaks.ToArray())); // Console.WriteLine(string.Join(",", values.ToArray())); // Console.WriteLine(string.Join(",", levels.ToArray())); //return valleys; return valleys; } } }
/* * 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.Collections.Generic; using System.Linq; using MathNet.Numerics; using MathNet.Numerics.LinearAlgebra; namespace QuantConnect.Indicators { public class SlopeIndicator : Indicator { private RollingWindow<decimal> highs; private bool _peaks; private double _peakinessThres; public SlopeIndicator(string name, int period, bool peaks, double peakinessThres = 1e-8) : base(name) { highs = new RollingWindow<decimal>(period); _peaks = peaks; _peakinessThres = peakinessThres; } /// <summary> /// Computes the average value /// </summary> /// <param name="input">The data for the calculation</param> /// <returns>The average value</returns> protected override decimal ComputeNextValue(IndicatorDataPoint input) { highs.Add(input.Value); if(!IsReady) { return 0; } decimal[] h = highs.ToArray(); Array.Reverse(h); List<int> peakindexes = _peaks?HHLL.PeakinessTest(h,_peakinessThres):HHLL.ValleysTest(h, _peakinessThres); List<double> peakvalues = new List<double>(); foreach(int index in peakindexes) { peakvalues.Add((double)h[index]); } if(peakvalues.Count<2) { return 0; } double[] t = Vector<double>.Build.Dense(peakvalues.Count, i => i + 1).ToArray(); var slope = Fit.Line(x: t, y: peakvalues.ToArray()); return (decimal)slope.Item2; } /// <summary> /// Returns whether the indicator will return valid results /// </summary> public override bool IsReady { get { return highs.IsReady; } } /// <summary> /// Resets the average to its initial state /// </summary> public override void Reset() { highs.Reset(); base.Reset(); } } }