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