Overall Statistics |
Total Trades 11 Average Win 9.88% Average Loss -2.25% Compounding Annual Return 6.196% Drawdown 9.000% Expectancy 2.236 Net Profit 50.942% Sharpe Ratio 0.814 Probabilistic Sharpe Ratio 27.967% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 4.39 Alpha 0.055 Beta -0.019 Annual Standard Deviation 0.065 Annual Variance 0.004 Information Ratio -0.319 Tracking Error 0.175 Treynor Ratio -2.817 Total Fees $146.50 |
/* This program was developed by Quantify and is a template program. Usage and marketing of this program is permitted. www.quantify-co.com */ namespace QuantConnect.Algorithm.CSharp { public class HorizontalTachyonChamber : QCAlgorithm { // ticker to be observed private readonly string security = "SPY"; // resolution for the stock (works with all resolutions) public readonly Resolution resolution = Resolution.Daily; // tecnology sector variables private ZigZagHighLow zzhl; public override void Initialize() { // sets brokerage model to AlphaStreams SetBrokerageModel(BrokerageName.AlphaStreams); // set backtesting parameters SetStartDate(2014, 1, 1); SetCash(1000000); // add ticker to universe AddEquity(security, resolution); // initialize ticker history var history = History(security, 100, resolution); List<TradeBar> list = new List<TradeBar>(); foreach(TradeBar tb in history) list.Add(tb); // initialize ATR AverageTrueRange atr = ATR(security, 10); // define the zzhl zzhl = new ZigZagHighLow(security, 100, 0.1m, atr, 0.5m, list); } /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// Slice object keyed by symbol containing the stock data public override void OnData(Slice data) { // updates the zzhl zzhl.update(Securities[security].High, Securities[security].Low); // check for position entry if(zzhl.getDirection() && !Portfolio.Invested) { SetHoldings(security, 0.5m); } else if(!zzhl.getDirection() && Portfolio.Invested) { Liquidate(security); } } // ZigZagHighLow indicator class // uses default moving average // reference: https://www.investopedia.com/terms/z/zig_zag_indicator.asp public class ZigZagHighLow { // symbol to be observed private string ticker = ""; // default indicator length private int length = 100; // percent change: default daily private decimal percent_change = 0.02m; // index of last high retracement private int high_index = 0; // index of last low retracement private int low_index = 0; // direction // true = up, false = down private bool dir = false; // rolling window high values private RollingWindow<decimal> high_values; // rolling window opening values private RollingWindow<decimal> low_values; // ATR indicator private AverageTrueRange atr; // atr reversal calculation private decimal atr_reversal; // nullified private bool nullify = false; // default constructor public ZigZagHighLow(string ticker, int length, decimal percent_change, AverageTrueRange atr, decimal atr_reversal, List<TradeBar> history) { // init ticker; default = "" this.ticker = ticker; // init length; default = 100 this.length = length; // init percent change; default = 0.0m; this.percent_change = percent_change; // init rolling windows high_values = new RollingWindow<decimal>(length); low_values = new RollingWindow<decimal>(length); // init default value high_values.Add(-1000000.0m); low_values.Add(1000000.0m); // init atr this.atr = atr; this.atr_reversal = atr_reversal; // inits high and low values foreach(TradeBar tb in history) { high_values.Add(tb.High); low_values.Add(tb.Low); } } // update the values for low and high rolling windows public void update(decimal high, decimal low) { // update indexes high_index++; low_index++; // update RollingWindows high_values.Add(high); low_values.Add(low); checkDir(high, low); } // used to update which direction the ticker is moving in private void checkDir(decimal high, decimal low) { // checks for reversal in upward direction if(!dir) { if(low < ((getHigh() * (1 - percent_change)) - (atr * atr_reversal))) { dir = true; // signal low reversal // set index for low value to 0 low_index = 0; } // checks for reversal in downward direction } else { if(high > ((getLow() * (1 + percent_change)) + (atr * atr_reversal))) { dir = false; // signal high reversal // set index for high value to 0 high_index = 0; } } } // returns highest value since last high reversal public decimal getHigh() { if(high_index >= high_values.Count) high_index = high_values.Count - 1; decimal high = high_values[high_index]; for(int i = high_index; i >= 0; i--) if(high_values[i] > high) { high = high_values[i]; high_index = i; } return high; } // returns lowest value since last low reversal public decimal getLow() { if(low_index >= low_values.Count) low_index = low_values.Count - 1; decimal low = low_values[low_index]; for(int i = low_index; i >= 0; i--) if(low_values[i] < low) { low = low_values[i]; low_index = i; } return low; } // gets direction of current stock // true = long; false = short public bool getDirection() { return low_index > high_index; } } } }