| 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
}