| Overall Statistics |
|
Total Trades 566 Average Win 8.42% Average Loss -3.20% Compounding Annual Return 14.758% Drawdown 60.000% Expectancy 0.214 Net Profit 221.104% Sharpe Ratio 0.473 Loss Rate 67% Win Rate 33% Profit-Loss Ratio 2.63 Alpha NaN Beta NaN Annual Standard Deviation 0.435 Annual Variance 0.189 Information Ratio NaN Tracking Error NaN Treynor Ratio NaN Total Fees $1132.00 |
namespace QuantConnect
{
public class FXMomentumTests : QCAlgorithm
{
List<string> _symbols = new List<string>() { "EURUSD", "GBPUSD", "AUDUSD", "EURGBP", "EURJPY", "GBPAUD", "NZDUSD", "USDCAD", "USDCHF", "USDJPY" };
TradeBars _bars = new TradeBars();
private Dictionary<string, SymbolData> _symbolData = new Dictionary<string, SymbolData>();
//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(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;
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)
{
_data._q = _data._sd;
} else
{
_data._q = 1;
}
Plot("Indicator "+_data.Symbol, "w", _data._q);
if(Portfolio[_data.Symbol].IsLong && _data._smaF < _data._smaS)
{
Liquidate(_data.Symbol);
}
if(Portfolio[_data.Symbol].IsShort && _data._smaF > _data._smaS)
{
Liquidate(_data.Symbol);
}
//------------------------------------------------------------------------------------------ ENTRIES
if (!Portfolio[_data.Symbol].Invested && _data._smaF > _data._smaS)
{
if(_data._sd != 0)
{
SetHoldings(_data.Symbol, 1);
}
}
if (!Portfolio[_data.Symbol].Invested && _data._smaF < _data._smaS)
{
if(_data._sd != 0)
{
SetHoldings(_data.Symbol, -1);
}
}
}
} // 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 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();
}
}
} // close algo
}