Overall Statistics |
Total Trades 356 Average Win 0.12% Average Loss -0.09% Annual Return 20.281% Drawdown 3.100% Expectancy 0.609 Net Profit 29.215% Sharpe Ratio 4.9 Loss Rate 30% Win Rate 70% Profit-Loss Ratio 1.31 Trade Frequency Daily trades |
// using System; using System.Collections; using System.Collections.Generic; using System.Globalization; namespace QuantConnect { // // Storage for each user trade: // class UserTrade { //Initialize variables: public DateTime Date = new DateTime(); public string Symbol = ""; public int Quantity = 0; public decimal LimitPrice = 0; //Initialize the User's Trade: public UserTrade(string csvRaw) { //Convert the string string[] csv = csvRaw.Split(','); //Initialize Parameters: try { Date = DateTime.ParseExact(csv[0], "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture); Symbol = csv[1]; Quantity = Convert.ToInt32(csv[2]); LimitPrice = Convert.ToDecimal(csv[3]); } catch { //Do nothing, use defaults: } } } }
// QuantConnect Simulator C# File, Created on 8-4-2013 by Jared Broad using System; using System.Collections; using System.Collections.Generic; using System.IO; namespace QuantConnect { using QuantConnect.Securities; using QuantConnect.Models; public static class Extensions { /// <summary> /// Convert CSV Strings to Memory Stream /// </summary> /// <param name="str">String to convert to stream</param> /// <returns>StreamReader</returns> public static Stream ToStream(this string str) { MemoryStream stream = new MemoryStream(); StreamWriter writer = new StreamWriter(stream); writer.Write(str); writer.Flush(); stream.Position = 0; return stream; } } }
using System; using System.Net; using System.Linq; using System.IO; using System.Collections; using System.Collections.Generic; namespace QuantConnect { using QuantConnect.Securities; using QuantConnect.Models; // // Order Processing Algorithm: // -> Use a list of orders to generate a report. // -> URL to CSV File with format: Ymd-H:i:s, symbol, quantity , limit price // public class OrderProcessingAlgorithm : QCAlgorithm, IAlgorithm { //Configurable Parameters: decimal cash = 1000000; int maxOrders = 100000; int maxSymbols = 500; string tradeRecordUrl = "https://dl.dropboxusercontent.com/s/a5ubudg2ta1f1pv/EODTradeRecord_v5.csv?dl=1&token_hash=AAFRkNsWBokJLgufZlZnfGZ1RJySLpBeRYXetKB2FBM9Uw"; //"https://www.quantconnect.com/cache/ExampleTradeRecord.csv"; SecurityType marketType = SecurityType.Equity; Resolution resolution = Resolution.Minute; //Automatically configured from the file: DateTime startDate = new DateTime(2013, 12, 12); DateTime endDate = new DateTime(2012, 1, 1); List<string> symbols = new List<string>(); //Working Variables: bool sentInformation = false; List<UserTrade> trades = new List<UserTrade>(); long memory = 0; //Set the parameters for the backtest: public override void Initialize() { // Obtain measurements after creating the new byte[] memory = System.GC.GetTotalMemory(true); //Basic Backtest Parameters: SetCash(cash); //Download the Orders: Store file in a public dropbox/gdrive link. https://www.quantconnect.com/cache/ExampleTradeRecord.csv try { using(WebClient netClient = new WebClient()) { string rawFile = netClient.DownloadString(tradeRecordUrl); string[] lines = rawFile.Split('\n'); foreach (string line in lines) { if (trades.Count() < maxOrders) { //Create the trade storage class: UserTrade trade = new UserTrade(line); //Error check: if (trade.Symbol.Trim() == "") continue; //Look through the trades list, find symbols: if (!symbols.Contains(trade.Symbol)) { if (symbols.Count() < maxSymbols) { symbols.Add(trade.Symbol); AddSecurity(marketType, trade.Symbol, resolution); } else { //Fatal error -- don't continue analysis: Error("Too many symbols"); } } //Add to trade list: trades.Add(trade); //Find the earliest/latest date for start/end date: if (trade.Date < startDate) startDate = trade.Date; if (trade.Date > endDate) endDate = trade.Date; } } } memory = (System.GC.GetTotalMemory(true) - memory); //Set the determined start and end dates: SetStartDate(startDate); SetEndDate(endDate); SetRunMode(RunMode.Series); } catch (Exception err) { Debug("Error initializing user trades from CSV: " + err.Message); } } //Handle TradeBar Events: a TradeBar occurs on every time-interval public override void OnTradeBar(Dictionary<string, TradeBar> data) { List<UserTrade> executedTrades = new List<UserTrade>(); if (!sentInformation) { sentInformation = true; Debug("Order Processing Started: You have " + symbols.Count() + " unique symbols, starting analysis on the " + startDate.ToShortDateString() + " and finishing on " + endDate.ToShortDateString() + " requiring " + (memory/1024/1024) + " MB of RAM to load the orders"); } //Select the trades in list which match this moment in time (to nearest 'resolution' period). List<UserTrade> activeTrades = (from trade in trades where trade.Date <= Time select trade).ToList(); //Place the order: if (activeTrades.Count() > 0) { foreach (UserTrade trade in activeTrades) { if (Securities[trade.Symbol].Price > 0) { if (trade.Quantity > 0) //buy ASAP - normally at open w assumption specified time=9:30 { Order(trade.Symbol, trade.Quantity); executedTrades.Add(trade); } else //Sell today, at any time price meets limit - time specified must be 9:30 so as to scan all day { if (Securities[trade.Symbol].Price >= trade.LimitPrice) { Order(trade.Symbol, trade.Quantity); executedTrades.Add(trade); } else if (Time.Hour == 15 && Time.Minute == 58) //EOD - We sell now. Limit Price should have been met earlier!? { Order(trade.Symbol, trade.Quantity); executedTrades.Add(trade); Log("Sold at EOD without meeting Limit Price : " + Time.ToShortDateString() + ", Symbol:" + trade.Symbol + ", Limit:" + trade.LimitPrice.ToString() + ", EOD Price:" + Securities[trade.Symbol].Price.ToString()); } } } } } //Remove these trades to make it faster for large lists the next time around. //Passed by reference so can remove by hashId. foreach (UserTrade trade in executedTrades) { trades.Remove(trade); } } } }