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

	
}