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