Overall Statistics |
Total Trades 3126 Average Win 0.57% Average Loss -0.46% Compounding Annual Return 118.728% Drawdown 17.200% Expectancy 0.176 Net Profit 290.107% Sharpe Ratio 3.052 Loss Rate 47% Win Rate 53% Profit-Loss Ratio 1.24 Alpha 0 Beta 0 Annual Standard Deviation 0.264 Annual Variance 0.07 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $54376.74 |
/* * 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 System.Net; using System.Threading.Tasks; using QuantConnect.Data.Market; using QuantConnect.Data.UniverseSelection; using Newtonsoft.Json; namespace QuantConnect.Algorithm.CSharp { /// <summary> /// In this algortihm we show how you can easily use the universe selection feature to fetch symbols /// to be traded using the AddUniverse method. This method accepts a function that will return the /// desired current set of symbols. Return Universe.Unchanged if no universe changes should be made /// </summary> public class DropboxUniverseSelectionAlgorithm : QCAlgorithm { public DateTime current_date; List<OrderTicket> MyLimitOrders = new List<OrderTicket>(); // the changes from the previous universe selection private SecurityChanges _changes = SecurityChanges.None; // only used in backtest for caching the file results private readonly Dictionary<DateTime, List<string>> _backtestSymbolsPerDay = new Dictionary<DateTime, List<string>>(); public decimal _price; /// <summary> /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. /// </summary> /// <seealso cref="QCAlgorithm.SetStartDate(System.DateTime)"/> /// <seealso cref="QCAlgorithm.SetEndDate(System.DateTime)"/> public override void Initialize() { // this sets the resolution for data subscriptions added by our universe UniverseSettings.Resolution = Resolution.Minute; UniverseSettings.Leverage = 2; // set our start and end for backtest mode SetStartDate(2010, 1, 4); SetEndDate(2011, 10, 1); SetCash(100000); Chart plotter = new Chart("Plotter"); plotter.AddSeries(new Series("SPY", SeriesType.Line, index:0)); AddChart(plotter); // define a new custom universe that will trigger each day at midnight AddUniverse("my-dropbox-universe", Resolution.Daily, dateTime => { const string liveUrl = @"https://www.dropbox.com/s/2az14r5xbx4w5j6/daily-stock-picker-live.csv?dl=1"; const string backtestUrl = @"https://www.dropbox.com/s/zeiwihafw78qqq4/dataforqc2.csv?dl=1"; var url = LiveMode ? liveUrl : backtestUrl; using (var client = new WebClient()) { // handle live mode file format n if (LiveMode) { SetBlackList("OPK","AYR","CCD","KBIO"); var signals = GetSignal(checkdate(), 4); string[] stocks = new string[4]; var count = 0; foreach (var stock in signals){ stocks[count] = stock.Ticker; count++; } return stocks; /* // fetch the file from dropbox var file = client.DownloadString(url); // if we have a file for today, break apart by commas and return symbols if (file.Length > 0) return file.ToCsv(); // no symbol today, leave universe unchanged return Universe.Unchanged; */ } // backtest - first cache the entire file if (_backtestSymbolsPerDay.Count == 0)// { // fetch the file from dropbox only if we haven't cached the result already var file = client.DownloadString(url); // split the file into lines and add to our cache foreach (var line in file.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)) { var csv = line.ToCsv(); var date = DateTime.ParseExact(csv[0], "yyyyMMdd", null); var symbols = csv.Skip(1).ToList(); _backtestSymbolsPerDay[date] = symbols; //foreach (var symbol in symbols){ // Console.Write(Time.ToString()+ " " +symbol); //} } } // if we have symbols for this date return them, else specify Universe.Unchanged List<string> result; if (_backtestSymbolsPerDay.TryGetValue(dateTime.Date, out result)) { return result; } return Universe.Unchanged; } }); } /// <summary> /// Stock data event handler /// </summary> /// <param name="data"></param> public void OnData(TradeBars data) { if (current_date == Time.Date) return; var percentage = 1m/4; if (Time.TimeOfDay < new TimeSpan(10, 30, 00)){ //THIS IS PART 1 if (Time.TimeOfDay == new TimeSpan(9, 31, 00)){ foreach (var symbol in _backtestSymbolsPerDay[Time.Date]) { _price = 0; _price = ((decimal)Securities[symbol].Price); if (_price != 0) { var quantity = (int)(double)(Portfolio.Cash/_price/4); var newTicket = LimitOrder(symbol, quantity, _price * .9975m); MyLimitOrders.Add(newTicket); //Log("New Limit Order: " + newTicket.Symbol.ToString() + " | $" + newTicket.Get(OrderField.LimitPrice).ToString("0.00")); } } } if (Time.TimeOfDay == new TimeSpan(9, 40, 00)){ var OrderTicketToUpdate = MyLimitOrders; foreach (var OrderTicketToCheck in OrderTicketToUpdate) { if (OrderTicketToCheck != null){ var _price = Securities[OrderTicketToCheck.Symbol].Close; if (_price != 0) { if (OrderTicketToCheck.Status != OrderStatus.Filled){ OrderTicketToCheck.Update(new UpdateOrderFields{LimitPrice = _price * .9992m}); //Log("Updated Limit Price: " + OrderTicketToCheck.Symbol.ToString() + " | $" + (_price * .999m).ToString("0.00")); } else { // Log("Order Filled: " + OrderTicketToCheck.Symbol.ToString()); } } } } } if (Time.TimeOfDay == new TimeSpan(9, 52, 00)){ var OrderTicketToUpdate = MyLimitOrders; foreach (var OrderTicketToCheck in OrderTicketToUpdate) { if (OrderTicketToCheck != null){ var _price = Securities[OrderTicketToCheck.Symbol].Close; if (_price != 0) { if (OrderTicketToCheck.Status != OrderStatus.Filled){ OrderTicketToCheck.Update(new UpdateOrderFields{LimitPrice = _price * 1.02m}); //Log("Updated Limit Price to MARKET: " + OrderTicketToCheck.Symbol.ToString() + " | $" + (_price * 1.02m).ToString("0.00")); } } } } } if (Time.TimeOfDay == new TimeSpan(10, 15, 00)){ MyLimitOrders.Clear(); } } if (Time.TimeOfDay > new TimeSpan(15, 55, 00)){ Liquidate(); } if (Time.TimeOfDay > new TimeSpan(15, 59, 00)){ current_date = Time.Date; } //var timeout = Task.Delay(TimeSpan.FromSeconds(20)); //var work = Task.Run(() => { // start fresh // reset changes _changes = SecurityChanges.None; //}); //Task.WaitAny(timeout, work); } /* public override void OnEndOfDay(string symbol) { Liquidate(); } */ /// <summary> /// Event fired each time the we add/remove securities from the data feed /// </summary> /// <param name="changes"></param> public override void OnSecuritiesChanged(SecurityChanges changes) { // each time our securities change we'll be notified here _changes = changes; } public static void SetBlackList(params string[] tickers) { var joined = string.Join(",", tickers); using (var wc = new WebClient()) { wc.DownloadString("ONLY IN LIVE" + joined); } } public static List<SignalStock> GetSignal(DateTime date, int count = 10) { using (var wc = new WebClient()) { var str = wc.DownloadString(string.Format("ONLY IN LIVE", date.Year, date.Month, date.Day, count)); return JsonConvert.DeserializeObject<List<SignalStock>>(str); } } private static DateTime checkdate() { if ((int)(DateTime.Now.DayOfWeek) != 1) { return DateTime.Now.AddDays(-1); } else { return DateTime.Now.AddDays(-3); } } } public class SignalStock { public string Ticker; public List<InsiderTransaction> Transactions; public double StockSignal; public StockDetails Details; public InsiderTransaction MainTransaction; } public class InsiderTransaction { public int? ExpertRank { get; set; } public DateTime Date { get; set; } public string OperationRatingString { get; set; } public string InsiderOperationType { get; set; } public string Ticker { get; set; } public string StockDisplayName { get; set; } public bool IsDirector { get; set; } public bool IsOfficer { get; set; } public string OfficerName { get; set; } public bool IsTenPercentOwner { get; set; } public decimal? Value { get; set; } public bool IsInformative { get; set; } public long? MarketCap { get; set; } public long InsiderOperationId { get; set; } public string InsiderName { get; set; } public double Signal { get; set; } } public class StockDetails { public string yLow; public string ticker { get; set; } public string pe { get; set; } public string marketCap { get; set; } public string openPrice { get; set; } public string eps { get; set; } public string divPerYield { get; set; } public string fiscalDiv { get; set; } public string beta { get; set; } public string shares { get; set; } public string market { get; set; } public string instOwn { get; set; } public string low { get; set; } public string high { get; set; } public string price { get; set; } public string yHigh { get; set; } public string range { get; set; } public string changeAmount { get; set; } public string changePercent { get; set; } public string average { get; set; } public string volume { get; set; } public string volumeAndAvg { get; set; } public string prevClose { get; set; } public string bid { get; set; } public string ask { get; set; } public string oneYearTargetEst { get; set; } public DateTime? nextEarningDate { get; set; } public string daysRange { get; set; } public string range52Weeks { get; set; } public string low52Weeks { get; set; } public string high52Weeks { get; set; } public string avgVol3Months { get; set; } } }