Overall Statistics |
Total Trades 396 Average Win 2.31% Average Loss -2.46% Compounding Annual Return 13.079% Drawdown 42.900% Expectancy 0.258 Net Profit 209.711% Sharpe Ratio 0.516 Loss Rate 35% Win Rate 65% Profit-Loss Ratio 0.94 Alpha 0.108 Beta -0.025 Annual Standard Deviation 0.206 Annual Variance 0.043 Information Ratio 0.224 Tracking Error 0.273 Treynor Ratio -4.245 Total Fees $798.94 |
namespace QuantConnect { public class Mundo : QCAlgorithm { //List of Currencies you would like to trade and get the indexes for List<string> _symbols = new List<string>() { "EURUSD", "GBPUSD", "AUDUSD", "NZDUSD"}; TradeBars _bars = new TradeBars(); private Dictionary<string, SymbolData> _symbolData = new Dictionary<string, SymbolData>(); public readonly int RollingWindowSize = 2; public readonly TimeSpan BarPeriod = TimeSpan.FromDays(1); //parameters int _normPeriod = 60; int _period = 20; //Initialize the data and resolution you require for your strategy: public override void Initialize() { //Start and End Date range for the backtest: SetStartDate(2007, 4, 1); // SetEndDate(2007, 5, 1); SetEndDate(DateTime.Now.Date.AddDays(-1)); //Cash allocation SetCash(30000); // initialize data for all the symbols foreach (var symbol in _symbols) { _symbolData.Add(symbol, new SymbolData(symbol, SecurityType.Forex, BarPeriod, RollingWindowSize)); } //Set forex securities and Consolidate all the data foreach (var kvp in _symbolData) { var symbolData = kvp.Value; //AddSecurity(symbolData.SecurityType, symbolData.Symbol, Resolution.Hour); AddForex(symbolData.Symbol, Resolution.Hour, "fxcm"); // define a consolidator to consolidate data for this symbol on the requested period var consolidator = new TradeBarConsolidator(BarPeriod); // define indicators symbolData._sd = new StandardDeviation(_period); symbolData._min = new Minimum(_normPeriod); symbolData._max = new Maximum(_normPeriod); //update indicators consolidator.DataConsolidated += (sender, bar) => { // 'bar' here is our newly consolidated data symbolData._min.Update(bar.Time, symbolData._portfolio); symbolData._max.Update(bar.Time, symbolData._portfolio); symbolData._sd.Update(bar.Time, bar.Close); // 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); } } //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { UpdateBars(data); if (_bars.Count != _symbols.Count) return; decimal _totalSd = 0; decimal _beta = 0; decimal _prt = 0; // Calculate total SD foreach (var _data in _symbolData.Values) { if (!_data._sd.IsReady) return; if (_data._sd != 0) { _totalSd += _data._sd; _beta += _data._sd; } } foreach (var _data in _symbolData.Values) { //make portfolio with Mundo index beta weights if (_beta != 0) _prt += _bars[_data.Symbol].Close * _data._sd / (_beta / 4m); } foreach (var _data in _symbolData.Values) { _data._portfolio = _prt; // Do a basic 0-1 Min-Max Normalization to normalize all the values if ((_data._max - _data._min) != 0) _data._norm = (_prt - _data._min) / (_data._max - _data._min); //------------------------------------------------------------------------------------------ EXITS if (Portfolio[_data.Symbol].IsLong && _data._norm > 1m) { Liquidate(); } if (Portfolio[_data.Symbol].IsShort && _data._norm < 0m) { Liquidate(); } //------------------------------------------------------------------------------------------ ENTRIES if (!Portfolio[_data.Symbol].Invested && _data._norm > 0 && _data._prenorm < 0) { if ((_beta / 4m) != 0 && _data._sd != 0) SetHoldings(_data.Symbol, 0.4m / (_data._sd / (_beta / 4m))); } if (!Portfolio[_data.Symbol].Invested && _data._norm < 1m && _data._prenorm > 1m) { if ((_beta / 4m) != 0 && _data._sd != 0) SetHoldings(_data.Symbol, -0.6m / (_data._sd / (_beta / 4m))); } _data._prenorm = _data._norm; //Keep track of the previous normalized values } } // end of ondata //Update the global "_bars" object private void UpdateBars(TradeBars data) { foreach (var bar in data.Values) { if (!_bars.ContainsKey(bar.Symbol)) { _bars.Add(bar.Symbol, bar); } _bars[bar.Symbol] = bar; } } //Create a class to manage all the Symbol Data class SymbolData { //stuff public readonly string Symbol; public readonly SecurityType SecurityType; public readonly RollingWindow<TradeBar> Bars; public readonly TimeSpan BarPeriod; //indcators public StandardDeviation _sd; public Minimum _min; public Maximum _max; public decimal _portfolio; public decimal _norm; public decimal _prenorm; // Constructor for the class public SymbolData(string symbol, SecurityType securityType, TimeSpan barPeriod, int windowSize) { Symbol = symbol; SecurityType = securityType; BarPeriod = barPeriod; Bars = new RollingWindow<TradeBar>(windowSize); _portfolio = new decimal(); _norm = new decimal(); _prenorm = new decimal(); } public bool IsReady { get { return Bars.IsReady && _sd.IsReady && _min.IsReady && _max.IsReady ; } } // public bool WasJustUpdated(DateTime current) // { // return Bars.Count > 0 && Bars[0].Time == current - BarPeriod; //} } } // end of algorithm }