Overall Statistics |
Total Trades 403 Average Win 9.09% Average Loss -2.88% Compounding Annual Return 17.898% Drawdown 53.500% Expectancy 0.321 Net Profit 284.257% Sharpe Ratio 0.523 Loss Rate 68% Win Rate 32% Profit-Loss Ratio 3.15 Alpha 0 Beta 0 Annual Standard Deviation 0.432 Annual Variance 0.187 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $806.00 |
namespace QuantConnect { public class FXMomentumTests : QCAlgorithm { List<string> _symbols = new List<string>() { "EURUSD", "AUDUSD", "EURJPY", "GBPAUD", "NZDUSD", "USDCAD", "USDJPY" }; TradeBars _bars = new TradeBars(); private Dictionary<string, SymbolData> _symbolData = new Dictionary<string, SymbolData>(); decimal _totalLots = 150m; //int _rebalancingPeriod = 30; //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(2015, 6, 1); //SetEndDate(DateTime.Now.Date.AddDays(-1)); //Cash allocation SetCash(10000); foreach (var symbol in _symbols) { //Add as many securities as you like. All the data will be passed into the event handler: AddSecurity(SecurityType.Forex, symbol, Resolution.Daily); _symbolData.Add(symbol, new SymbolData(symbol, this)); } } //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; foreach (var _data in _symbolData.Values) { if(!_data._sd.IsReady) return; if(!_data._smaF.IsReady) return; if(!_data._smaS.IsReady) return; if(_data._sd != 0) _totalSd += _data._sd; } foreach (var _data in _symbolData.Values) { //if(_data._sd != 0) Plot("Indicator "+_data.Symbol, "w", _data._sd); //------------------------------------------------------------------------------------------ EXITS if(Portfolio[_data.Symbol].IsLong && _data._smaF < _data._smaS) { Liquidate(_data.Symbol); } if(Portfolio[_data.Symbol].IsShort && _data._smaF > _data._smaS) { Liquidate(_data.Symbol); } decimal _qty = ((_data._sd) / _totalSd) * _totalLots; Plot("Indicator "+_data.Symbol, "w", _qty); //------------------------------------------------------------------------------------------ ENTRIES if(!Portfolio[_data.Symbol].Invested && _data._smaF > _data._smaS) { SetHoldings(_data.Symbol, _qty); _data.lastrebalance = _bars[_data.Symbol].Time; } if(!Portfolio[_data.Symbol].Invested && _data._smaF < _data._smaS) { SetHoldings(_data.Symbol, -_qty); _data.lastrebalance = _bars[_data.Symbol].Time; } //------------------------------------------------------------------------------------------ REBALANCE /*if(Portfolio[_data.Symbol].IsLong && (_bars[_data.Symbol].Time - _data.lastrebalance).TotalDays >= _rebalancingPeriod) { SetHoldings(_data.Symbol, _qty); _data.lastrebalance = _bars[_data.Symbol].Time; } Log("thist "+_bars[_data.Symbol].Time+" lastt "+_data.lastrebalance); if(Portfolio[_data.Symbol].IsShort && (_bars[_data.Symbol].Time - _data.lastrebalance).TotalDays >= _rebalancingPeriod) { SetHoldings(_data.Symbol, -_qty); _data.lastrebalance = _bars[_data.Symbol].Time; }*/ } } // end 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; } } class SymbolData { //parameters int _fastPeriod = 20; int _slowPeriod = 120; public DateTime lastrebalance; public readonly string Symbol; public readonly SimpleMovingAverage _smaS; public readonly SimpleMovingAverage _smaF; public readonly StandardDeviation _sd; public decimal _q; public SymbolData(string symbol, QCAlgorithm algorithm) { Symbol = symbol; _smaF = algorithm.SMA(symbol, _fastPeriod, Resolution.Daily); _smaS = algorithm.SMA(symbol, _slowPeriod, Resolution.Daily); _sd = algorithm.STD(symbol, _fastPeriod, Resolution.Daily); _q = new decimal(); lastrebalance = new DateTime(); } } } // close algo }