| Overall Statistics |
|
Total Trades 423 Average Win 0.35% Average Loss -0.26% Compounding Annual Return -31.743% Drawdown 20.600% Expectancy -0.058 Net Profit -6.835% Sharpe Ratio -0.714 Loss Rate 60% Win Rate 40% Profit-Loss Ratio 1.34 Alpha -0.161 Beta 0.185 Annual Standard Deviation 0.221 Annual Variance 0.049 Information Ratio -0.738 Tracking Error 0.237 Treynor Ratio -0.852 |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
namespace QuantConnect.Algorithm.Examples
{
public class MultipleSymbolConsolidationAlgorithm : QCAlgorithm
{
public readonly TimeSpan BarPeriod = TimeSpan.FromHours(1);
public readonly int RollingWindowSize = 20;
public readonly Dictionary<string, SymbolData> _data = new Dictionary<string, SymbolData>();
decimal _delta;
/*public readonly IReadOnlyList<string> EquitySymbols = new List<string>
{
"AAPL",
"SPY",
"IBM"
};*/
public readonly IReadOnlyList<string> ForexSymbols = new List<string>
{
"EURUSD",
//"USDJPY",
"EURGBP",
"EURCHF",
"USDCAD",
"USDCHF",
"AUDUSD",
"NZDUSD",
};
public override void Initialize()
{
SetStartDate(2014, 12, 01);
SetEndDate(DateTime.Now.Date.AddDays(-1));
//Cash allocation
SetCash(1000);
// initialize our equity data
/*foreach (var symbol in EquitySymbols)
{
_data.Add(symbol, new SymbolData(symbol, SecurityType.Equity, BarPeriod, RollingWindowSize));
}*/
// initialize our forex data
foreach (var symbol in ForexSymbols)
{
_data.Add(symbol, new SymbolData(symbol, SecurityType.Forex, BarPeriod, RollingWindowSize));
}
// loop through all our symbols and request data subscriptions and initialize indicatora
foreach (var kvp in _data)
{
// this is required since we're using closures below, for more information
// see: http://stackoverflow.com/questions/14907987/access-to-foreach-variable-in-closure-warning
var symbolData = kvp.Value;
// request data subscription
AddSecurity(symbolData.SecurityType, symbolData.Symbol, Resolution.Minute);
// define a consolidator to consolidate data for this symbol on the requested period
var consolidator = new TradeBarConsolidator(BarPeriod);
// define our indicator
symbolData._sma1 = new SimpleMovingAverage(symbolData.Symbol + 10, 10);
symbolData._sma2 = new SimpleMovingAverage(symbolData.Symbol + 20, 20);
symbolData._slow = new SimpleMovingAverage(symbolData.Symbol + 5, 5);
// wire up our consolidator to update the indicator
consolidator.DataConsolidated += (sender, bar) =>
{
// 'bar' here is our newly consolidated data
symbolData._sma1.Update(bar.Time, bar.Close);
symbolData._sma2.Update(bar.Time, bar.Close);
symbolData._slow.Update(bar.Time, (symbolData._sma1 - symbolData._sma2));
// we're also going to add this bar to our rolling window so we have access to it later
symbolData.Bars.Add(bar);
};
// we need to add this consolidator so it gets auto updates
SubscriptionManager.AddConsolidator(symbolData.Symbol, consolidator);
}
}
public void OnData(TradeBars data)
{
foreach (var symbolData in _data.Values)
{
// this check proves that this symbol was JUST updated prior to this OnData function being called
if (symbolData.IsReady && symbolData.WasJustUpdated(data.Time))
{
_delta = symbolData._sma1 - symbolData._sma2;
if (Portfolio[symbolData.Symbol].Invested && _delta < symbolData._slow)
{
Liquidate(symbolData.Symbol);
}
if (!Portfolio[symbolData.Symbol].Invested && _delta > symbolData._slow)
{
MarketOrder(symbolData.Symbol, 1000);
}
}
}
}
/*public override void OnEndOfDay()
{
int i = 0;
foreach (var kvp in _data.OrderBy(x => x.Value.Symbol))
{
// we have too many symbols to plot them all, so plot ever other
if (kvp.Value.IsReady && ++i%2 == 0)
{
Plot(kvp.Value.Symbol, kvp.Value._sma1);
}
}
}*/
public class SymbolData
{
public readonly string Symbol;
public readonly SecurityType SecurityType;
public readonly RollingWindow<TradeBar> Bars;
public readonly TimeSpan BarPeriod;
public SimpleMovingAverage _sma1;
public SimpleMovingAverage _sma2;
public SimpleMovingAverage _slow;
public SymbolData(string symbol, SecurityType securityType, TimeSpan barPeriod, int windowSize)
{
Symbol = symbol;
SecurityType = securityType;
BarPeriod = barPeriod;
Bars = new RollingWindow<TradeBar>(windowSize);
}
public bool IsReady
{
get {
return Bars.IsReady
&& _sma1.IsReady
&& _sma2.IsReady
&& _slow.IsReady
;}
}
public bool WasJustUpdated(DateTime current)
{
return Bars.Count > 0 && Bars[0].Time == current - BarPeriod;
}
}
}
}