Overall Statistics |
Total Trades 1242 Average Win 2.43% Average Loss -2.54% Compounding Annual Return 15.169% Drawdown 33.700% Expectancy 0.107 Net Profit 268.257% Sharpe Ratio 0.53 Loss Rate 43% Win Rate 57% Profit-Loss Ratio 0.96 Alpha 0.125 Beta 0.021 Annual Standard Deviation 0.238 Annual Variance 0.057 Information Ratio 0.291 Tracking Error 0.293 Treynor Ratio 5.98 Total Fees $6064.30 |
namespace QuantConnect { public class VAAMACrossFX : QCAlgorithm { string _symbol = "EURUSD"; TrailingStop _trailStop; TrailingStop _trailStopSh; List<string> _symbols = new List<string>() { "EURUSD" }; //helping objects //private TimeSpan _barPeriod = TimeSpan.FromDays(1); //private Consolidator _consolidator; TradeBars _bars = new TradeBars(); //windows of data RollingWindow<TradeBar> _window = new RollingWindow<TradeBar>(75); RollingWindow<TradeBar> _windowH = new RollingWindow<TradeBar>(2000); RollingWindow<decimal> _mW = new RollingWindow<decimal>(45); RollingWindow<decimal> _mHW = new RollingWindow<decimal>(1200); RollingWindow<decimal> _vamaW = new RollingWindow<decimal>(40); RollingWindow<decimal> _residW = new RollingWindow<decimal>(40); RollingWindow<decimal> _vamaHW = new RollingWindow<decimal>(1200); RollingWindow<decimal> _residHW = new RollingWindow<decimal>(1200); //indicators SimpleMovingAverage _sma; RelativeStrengthIndex _rsi; StandardDeviation _sd; decimal _vamaHour; decimal _vamaDaily; decimal _prevamaHour; decimal _prevamaDaily; decimal _m; decimal _mL; decimal _mHL; decimal _residual; decimal _residualH; decimal _residualSm; decimal _residualHSm; decimal _prersi; //parameters int _volSmooth = 4; decimal _fast = 4; decimal _slow = 4; //Initialize the data and resolution you require for your strategy: public override void Initialize() { //Start and End Date range for the backtest: SetStartDate(2007, 7, 1); SetEndDate(DateTime.Now.Date.AddDays(-1)); //Cash allocation SetCash(10000); //benchmark SetBenchmark("SPY"); foreach (var symbol in _symbols) { //Setup Consolidator bar //_consolidator = new Consolidator(_barPeriod); //Add as many securities as you like. All the data will be passed into the event handler: AddSecurity(SecurityType.Forex, symbol, Resolution.Minute, true, 50, true); //Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.Raw); // define hourly consoldiator var _hourConsolidator = new TradeBarConsolidator(TimeSpan.FromHours(1)); _hourConsolidator.DataConsolidated += OnHour; SubscriptionManager.AddConsolidator(symbol, _hourConsolidator); // define daily consoldiator var _dailyConsolidator = new TradeBarConsolidator(TimeSpan.FromDays(1)); _dailyConsolidator.DataConsolidated += OnDaily; SubscriptionManager.AddConsolidator(symbol, _dailyConsolidator); } /*_sd = new StandardDeviation(30); _min = new Minimum(50); _max = new Maximum(50); _suml = new Sum(30); _sumh = new Sum(30);*/ _sma = new SimpleMovingAverage(400); _rsi = RSI(_symbol, 6, MovingAverageType.Simple, Resolution.Hour); _sd = STD(_symbol, 100, Resolution.Hour); //_slope = new AnnualizedExponentialSlope(180); //RegisterIndicator(_symbol, _slope, Resolution.Daily, Field.Close); } //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) { } //daily-------------------------------------------------------------------------------------------------------------------------------------------------------- public void OnDaily(object sender, TradeBar data) { //UpdateBars(data); //if (_bars.Count != _symbols.Count) return; //if (!_slope.IsReady) return; //if(_consolidator.Update(_bars[_symbol])) //{ //add symbol data to window _window.Add(data); if(!_window.IsReady) return; _m = Math.Max(Math.Max((_window[0].High - _window[1].Close), (_window[0].High - _window[0].Low)), Math.Max((_window[0].Low - _window[1].Close), 0)); _mW.Add(_m); if(!_mW.IsReady) return; _mL = LSMA(_mW, _volSmooth); if(_prevamaDaily != 0) { _vamaDaily = _prevamaDaily + _mL*_slow*(_window[0].Close - _prevamaDaily); } else { _vamaDaily = _window[0].Close; } _vamaW.Add(_vamaDaily); if(!_vamaW.IsReady) return; _residual = _window[0].Close - LSMA(_vamaW, 40); _residW.Add(_residual); if(!_residW.IsReady) return; _residualSm = LSMA(_residW, 40); //Log("vamas"+ _vamaSlow+" prev "+_prevamaSlow); //Plot("Indicators", "f", _vamaFast); Plot("Indicators", "s", _vamaDaily); Plot("Indicators", "p", _window[0].Close); //updates _prevamaDaily = _vamaDaily; //} //close of daily consolidator } // end of on daily //hourly-------------------------------------------------------------------------------------------------------------------------------------------------------- public void OnHour(object sender, TradeBar data) { if(!_rsi.IsReady) return; if(!_sd.IsReady) return; //add symbol data to window _windowH.Add(data); if(!_windowH.IsReady) return; decimal _mH = Math.Max(Math.Max((_windowH[0].High - _windowH[1].Close), (_windowH[0].High - _windowH[0].Low)), Math.Max((_windowH[0].Low - _windowH[1].Close), 0)); _mHW.Add(_m); if(!_mHW.IsReady) return; _mHL = LSMA(_mW, _volSmooth); if(_prevamaHour != 0) { _vamaHour = _prevamaHour + _mL*_fast*(_windowH[0].Close - _prevamaHour); } else { _vamaHour = _windowH[0].Close; } _vamaHW.Add(_vamaHour); if(!_vamaHW.IsReady) return; _residualH = _windowH[0].Close - LSMA(_vamaHW, 40); _residHW.Add(_residualH); if(!_residHW.IsReady) return; _residualHSm = LSMA(_residHW, 40); //update filter TradeBar bar; _sma.Update(data.Time, _sd); if(!_sma.IsReady) return; //Plot("IndicatorsH", "s", _vamaHour); //Plot("IndicatorsH", "p", _window[0].Close); //Plot("IndicatorsHRSI", "rsi", _rsi); Plot("Cash", "c", Portfolio.Cash); //exits if(_prevamaHour != 0) { decimal exitPrice = data.Close; if(Portfolio[_symbol].Invested) { //SL if(Securities[_symbol].Holdings.UnrealizedProfit < -Portfolio.TotalPortfolioValue*0.05m) { Liquidate(_symbol); } //TP /*if(Securities[_symbol].Holdings.UnrealizedProfit > -Portfolio.TotalPortfolioValue*0.02m) { Liquidate(_symbol); }*/ if(Portfolio[_symbol].IsLong) { if(_rsi > 70) { Liquidate(_symbol); } /*if(_trailStop.IsTrailingExit(_bars[_symbol], out exitPrice)) { Liquidate(_symbol); }*/ } if(Portfolio[_symbol].IsShort) { if(_rsi < 30) { Liquidate(_symbol); } /*if(_trailStop.IsTrailingExit(_bars[_symbol], out exitPrice)) { Liquidate(_symbol); }*/ } } //entries //if(!Portfolio[_symbol].Invested && _vamaHour > _prevamaHour && _vamaW[0] > _vamaW[1] && _residualSm > 0 && _residualHSm > 0 && _rsi > 40 && _prersi < 40&& _sd > 0.005m) //5.6% if(!Portfolio[_symbol].Invested && data.Close > _vamaHour && data.Close > _vamaW[0] && _residualSm > 0 && _residualHSm > 0 && _rsi > 40 && _prersi < 40 && _sd > 0.005m) //6.5% { SetHoldings(_symbol, 10); //_trailStop = new TrailingStop(data[_symbol].Close, 2, true); } else if(!Portfolio[_symbol].Invested && data.Close < _vamaHour && data.Close < _vamaW[0] && _residualSm < 0 && _residualHSm < 0 && _rsi < 60 && _prersi > 60 && _sd > 0.005m) //6.5% { SetHoldings(_symbol, -10); //_trailStopSh = new TrailingStop(data[_symbol].Close, 2, false); } } //updates _prevamaHour = _vamaHour; _prersi = _rsi; } // end of hour conslidator //calculate LSMA private decimal LSMA(RollingWindow<decimal> _dataW, int _lsmaPeriod) { decimal _lsma; decimal _delta = 0; //calculate lsma _delta = 0; for(int i=_lsmaPeriod; i >= 1; i--) { _delta += (i-(_lsmaPeriod+1)/3.0m)*_dataW[_lsmaPeriod-i]; } _lsma = _delta*6/(_lsmaPeriod*(_lsmaPeriod+1)); return _lsma; } //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; } } } }
using System; using System.Collections.Generic; using System.Linq; namespace QuantConnect { public class TrailingStop { public decimal TrailingStopValue {get;set;} decimal TrailingStopPercent{get;set;} bool IsLong {get;set;} public TrailingStop ( decimal stopValue, decimal stopPercent, bool isLongEntry ) { TrailingStopValue = stopValue; TrailingStopPercent = stopPercent; IsLong = isLongEntry; } public bool IsTrailingExit( TradeBar b, out decimal exitPrice) { bool rtn = false; exitPrice = 0; if ( IsLong == true) { if(TrailingStopValue != 0) { if ( b.Close / TrailingStopValue < 1-TrailingStopPercent/100) { exitPrice = b.Close; rtn = true; } } } else { // short if(TrailingStopValue != 0) { if ( b.Close / TrailingStopValue > 1+TrailingStopPercent/100 ) { exitPrice = b.Close; rtn = true; } } } // update Trailing stop if needed if ( rtn != true) { if ( IsLong == true && b.Close > TrailingStopValue) TrailingStopValue = b.Close; if ( IsLong == false && b.Close < TrailingStopValue) TrailingStopValue = b.Close; } return rtn; } // IsTrailingExit } // TrailingStop }