Overall Statistics |
Total Trades 0 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 -2.688 Tracking Error 0.134 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
/* This program was developed by Quantify and is property of Mario Sarli Usage and marketing of this program is permitted. Quantify Developer(s): Conor Flynn Date Created: 07/13/2021 Client: Mario Sarli Client ID: 341994651 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 { public class Main : QCAlgorithm { // BACKTESTING PARAMETERS // ================================================================================================================= // general settings: // set starting cash private int starting_cash = 100000; // backtesting start date time: // date setting variables private int start_year = 2021; private int start_month = 1; private int start_day = 1; // 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 enable_end_date = false; // date setting variables private int end_year = 2020; private int end_month = 1; private int end_day = 1; // universe settings: // data update resolution // changes how often the data updates and algorithm looks for entry // determines how often the function OnData runs // list of resolutions: // Resolution.Tick; Resolution.Second; Resolution.Minute; Resolution.Hour; Resolution.Daily private readonly Resolution resolution = Resolution.Second; // stock list // list of stocks you want in the universe // used in manual selection of universe // set selection_type = false for activation private readonly String[] manual_universe = new String[]{"SPY", "AAPL"}; // indicator settings: // length of the SMA for the base line (line 2, init line 4, 5) private readonly int length_base = 50; // base calculation type: (line 4, 5) // 1: OHLC4 // 2: (H+L) / 2 private static readonly int calculation_base = 1; // length of the SMA for the space line: (line 2, init line 21) private readonly int length_space = 50; // space calculation type: (line 21) // 1: (H-L) // 2: abs(C-O) private static readonly int calculation_space = 1; // space factor: (line 24) private static readonly decimal factor_space = 1.0m; // number of spacers from the base line (default 10) private readonly int count_space = 10; // ================================================================================================================= // creates new universe variable setting private List<StockData> universe = new List<StockData>(); // security changes variable private SecurityChanges securityChanges = SecurityChanges.None; public override void Initialize() { // set start date SetStartDate(start_year, start_month, start_day); // set end date if(enable_end_date) SetEndDate(end_year, end_month, end_day); // set starting cash SetCash(starting_cash); // add all equities into the universe foreach(string s in manual_universe) { AddEquity(s, resolution); // create StockData variable for security StockData sd = new StockData(); sd.algorithm = this; sd.ticker = s; sd.sma_base = new SimpleMovingAverage(length_base); sd.sma_space = new SimpleMovingAverage(length_space); sd.pos_space = new decimal[count_space]; sd.neg_space = new decimal[count_space]; // add stockdata to universe universe.Add(sd); } } // 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) { // loops through each stock in universe foreach(StockData sd in universe) { // update values sd.update(); // if data is not ready then skip if(!sd.IsReady) continue; // if long check for short if(sd.direction == 1 && sd.IsShort()) { // enter short } // if short check for long else if(sd.direction == -1 && sd.IsLong()) { // enter long } // if not in position wait for either else if(sd.direction == 0) { if(sd.IsLong()) { // enter long } else if(sd.IsShort()) { // enter short } } } } // default class containing all ticker information public class StockData { // QCAlgorithm variable public QCAlgorithm algorithm; // stock ticker public string ticker = ""; // simple moving average baseline (line 7) public SimpleMovingAverage sma_base; // spacing period (line 21) public SimpleMovingAverage sma_space; // stores all line space calculations public decimal[] pos_space; public decimal[] neg_space; // stores the prior and current index public int index = -10000; private int prev_index = -10000; // variable determining long, short, or null (1, -1, 0): public int direction = 0; // determines if data is ready public bool IsReady => sma_base.IsReady && sma_space.IsReady && index != -10000 && prev_index != -10000; // updates spacing calculations public void update() { // define security object Security sym = algorithm.Securities[ticker]; // Update SMAs UpdateSMA(sym); // Update Spacing UpdateSpacing(sym); } // updates the SMAs used for calculation private void UpdateSMA(Security sym) { // update the base sma decimal price; if(Main.calculation_base == 1) { // OHLC4 price = (sym.Open + sym.High + sym.Low + sym.Close) / 4; } else if(Main.calculation_base == 2) { // (H+L) / 2 price = (sym.High + sym.Low) / 2; } else { // invalid value algorithm.Error("INVALID <calculation_base> VALUE"); price = -1.0m; } // push to object sma_base.Update(algorithm.Time, price); // update the space sma if(Main.calculation_space == 1) { // (H-L) price = (sym.High - sym.Low); } else if(Main.calculation_space == 2) { // abs(C-O) price = Math.Abs(sym.Close - sym.Open); } else { // invalid value algorithm.Error("INVALID <calculation_space> VALUE"); price = -1.0m; } // push to object sma_space.Update(algorithm.Time, price); } // updates the indicies of the spacing arrays private void UpdateSpacing(Security sym) { // determine if above or below base if(sym.Price > sma_space) { // set 0 as base pos_space[0] = sma_space; // update spacing and determine where the price is at for(int i = 1; i < pos_space.Count(); i++) { pos_space[i] = sma_base + (sma_space * i * Main.factor_space); // if between prior index and current then set accoring if(sym.Price > pos_space[i - 1] && sym.Price < pos_space[i]) { prev_index = index; index = i; } } } else if(sym.Price < sma_space) { // set 0 as base neg_space[0] = sma_space; // update spacing and determine where the price is at for(int i = 1; i < neg_space.Count(); i++) { neg_space[i] = sma_base - (sma_space * i * Main.factor_space); // if between prior index and current then set accoring if(sym.Price < neg_space[i - 1] && sym.Price > neg_space[i]) { prev_index = index; index = i; } } } else { index = 0; } } // determines if the algorithm crossed long public bool IsLong() { return index > prev_index; } // determine if the algorithm crossed short public bool IsShort() { return index < prev_index; } } } }