| Overall Statistics |
|
Total Trades 10635 Average Win 0.03% Average Loss -0.06% Compounding Annual Return 5.267% Drawdown 5.700% Expectancy 0.028 Net Profit 18.396% Sharpe Ratio 1.202 Loss Rate 34% Win Rate 66% Profit-Loss Ratio 0.56 Alpha 0.056 Beta -0.019 Annual Standard Deviation 0.044 Annual Variance 0.002 Information Ratio -0.998 Tracking Error 0.128 Treynor Ratio -2.806 Total Fees $21294.00 |
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace QuantConnect
{
class BuyLowStrategy
{
// Fields
//private int symbolsN;
private int runsPerDay;
private int previousDaysN;
private Dictionary<string, bool> newDay = new Dictionary<string,bool>();
private Dictionary<string, decimal> previousValue = new Dictionary<string, decimal>();
private Dictionary<string, DateTime> previousValueDate = new Dictionary<string, DateTime>();
private Dictionary<string, decimal> accumulatedRun = new Dictionary<string, decimal>();
private Dictionary<string, decimal> valuePrevToRun = new Dictionary<string, decimal>();
private Dictionary<string, List<decimal>> intraDayRuns = new Dictionary<string, List<decimal>>();
private Dictionary<string, Queue<decimal>> dailyDownwardRuns = new Dictionary<string, Queue<decimal>>();
private Dictionary<string, Queue<decimal>> dailyUpwardRuns = new Dictionary<string, Queue<decimal>>();
private Dictionary<string, decimal> previousDaysDownwardRuns = new Dictionary<string, decimal>();
private Dictionary<string, decimal> previousDaysUpwardRuns = new Dictionary<string, decimal>();
private Dictionary<string, bool> isReady = new Dictionary<string, bool>();
private Dictionary<string, bool> turnAround = new Dictionary<string, bool>();
private Dictionary<string, int> orderSignal = new Dictionary<string, int>();
public Dictionary<string, bool> IsReady
{
get { return isReady; }
}
public Dictionary<string, bool> TurnAround
{
get { return turnAround; }
}
public Dictionary<string, int> OrderSignal
{
get { return orderSignal; }
}
// Constructor
public BuyLowStrategy(string[] symbols, int PreviousDaysN, int RunsPerDay)
{
//this.symbolsN = symbols.Length;
this.previousDaysN = PreviousDaysN;
this.runsPerDay = RunsPerDay;
foreach (string symbol in symbols)
{
intraDayRuns.Add(symbol, new List<decimal>());
dailyDownwardRuns.Add(symbol, new Queue<decimal>());
dailyUpwardRuns.Add(symbol, new Queue<decimal>());
previousValueDate.Add(symbol, new DateTime());
valuePrevToRun.Add(symbol, new decimal());
previousValue.Add(symbol, new decimal());
accumulatedRun.Add(symbol, new decimal());
isReady.Add(symbol, false);
turnAround.Add(symbol, false);
previousDaysDownwardRuns.Add(symbol, new decimal());
previousDaysUpwardRuns.Add(symbol, new decimal());
orderSignal.Add(symbol, 0);
newDay[symbol] = true;
}
}
// Add
public void AddSerieValue(string symbol, DateTime timeStamp, decimal serieValue)
{
bool sameDay;
DateTime actualValueDate = timeStamp.Date;
if (newDay[symbol])
{
// Day initialization
previousValueDate[symbol] = actualValueDate;
valuePrevToRun[symbol] = serieValue;
previousValue[symbol] = serieValue;
accumulatedRun[symbol] = 0;
//isReady[symbol] = false;
turnAround[symbol] = false;
newDay[symbol] = false;
}
sameDay = actualValueDate == previousValueDate[symbol].Date;
if (sameDay)
{
DayTripper(timeStamp, symbol, serieValue); // I quickly run out of ideas for good method's names.
}
else
{
DayEnd(symbol);
newDay[symbol] = true;
}
}
private void DayTripper(DateTime timeStamp, string symbol, decimal serieValue)
{
decimal valueDiff;
decimal brokenRun;
decimal previousAccum = accumulatedRun[symbol];
valueDiff = serieValue - previousValue[symbol];
if (valueDiff * previousAccum >= 0)
{
accumulatedRun[symbol] = previousAccum + valueDiff;
turnAround[symbol] = false;
}
else
{
accumulatedRun[symbol] = valueDiff;
turnAround[symbol] = true;
brokenRun = previousAccum / valuePrevToRun[symbol];
valuePrevToRun[symbol] = previousValue[symbol];
intraDayRuns[symbol].Add(brokenRun);
CheckOrders(symbol, brokenRun);
}
previousValue[symbol] = serieValue;
previousValueDate[symbol] = timeStamp;
}
private void DayEnd(string symbol)
{
decimal dayMeanDownwardRun;
decimal dayMeanUpwardRun;
dayMeanDownwardRun = (from run in intraDayRuns[symbol]
where run < 0
orderby run ascending
select run).Take(runsPerDay).DefaultIfEmpty().Average();
dayMeanUpwardRun = (from run in intraDayRuns[symbol]
where run > 0
orderby run descending
select run).Take(runsPerDay).DefaultIfEmpty().Average();
dailyDownwardRuns[symbol].Enqueue(dayMeanDownwardRun);
dailyUpwardRuns[symbol].Enqueue(dayMeanUpwardRun);
intraDayRuns[symbol].Clear();
if (dailyDownwardRuns[symbol].Count == previousDaysN) isReady[symbol] = true;
if (dailyDownwardRuns[symbol].Count > previousDaysN)
{
dailyDownwardRuns[symbol].Dequeue();
dailyUpwardRuns[symbol].Dequeue();
}
previousDaysDownwardRuns[symbol] = dailyDownwardRuns[symbol].DefaultIfEmpty().Average();
previousDaysUpwardRuns[symbol] = dailyUpwardRuns[symbol].DefaultIfEmpty().Average();
}
private void CheckOrders(string symbol, decimal brokenRun)
{
if (this.isReady[symbol])
{
orderSignal[symbol] = 0; // Do nothing
if (brokenRun < 0 && brokenRun < previousDaysDownwardRuns[symbol])
{
// Long order
orderSignal[symbol] = -1;
}
else if (brokenRun > 0 && brokenRun > previousDaysUpwardRuns[symbol])
{
// Short order
orderSignal[symbol] = 1;
}
}
}
}
}using System;
using System.Collections.Generic;
using QuantConnect.Indicators;
using QuantConnect.Data.Market;
namespace QuantConnect
{
/// <summary>
/// Basic template algorithm simply initializes the date range and cash
/// </summary>
public class IntradayBuyLow : QCAlgorithm
{
static string[] symbols = { "AAPL", "GOOGL", "IBM", "MSFT"};
BuyLowStrategy Strategy = new BuyLowStrategy(symbols, 5, 4);
Dictionary<string, ExponentialMovingAverage> ema = new Dictionary<string, ExponentialMovingAverage>();
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
SetStartDate(2012, 1, 1); //Set Start Date
SetEndDate(2015, 4, 15); //Set End Date
SetCash(100000); //Set Strategy Cash
// Find more symbols here: http://quantconnect.com/data
foreach (string symbol in symbols)
{
AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
//tradier does 1 dollar equity trades
Securities[symbol].TransactionModel = new ConstantFeeTransactionModel(1.00m);
ema.Add(symbol, EMA(symbol, 5, Resolution.Minute));
}
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="data">TradeBars IDictionary object with your stock data</param>
public void OnData(TradeBars data)
{
foreach (string symbol in symbols)
{
// write more comments! you'll thank yourself later when
// you forget why you did something :)
if (!ema[symbol].IsReady) return;
Strategy.AddSerieValue(symbol, Time, ema[symbol]);
if (Strategy.IsReady[symbol])
{
if (Portfolio[symbol].HoldStock)
{
if (Strategy.TurnAround[symbol])
{
Liquidate(symbol);
}
}
else
{
if (Strategy.OrderSignal[symbol] != 0)
{
EntryAndSetStopLoss(symbol, Strategy.OrderSignal[symbol]);
}
}
}
}
}
private void EntryAndSetStopLoss(string symbol, int signal)
{
decimal stopLossPrice;
int orderSize = SetOrderSize(signal);
SetHoldings(symbol, 0.25*signal);
//MarketOrder(symbol, orderSize);
//Debug((signal > 0) ? "Buy " : "Sell " + orderSize.ToString() + " "
// + symbol + " shares @ $" + Portfolio[symbol].HoldingsCost);
//stopLossPrice = Portfolio[symbol].HoldingsCost * SetStopLossCoef();
//StopMarketOrder(symbol, -orderSize, stopLossPrice);
//Debug("Stop loss order @ $" + stopLossPrice.ToString());
}
private int SetOrderSize(int signal)
{
// TO DO: Sizing model
return 100 * signal;
}
private decimal SetStopLossCoef()
{
return 0.95m;
}
}
}