Overall Statistics
Total Trades
3912
Average Win
0.27%
Average Loss
-0.27%
Compounding Annual Return
8.936%
Drawdown
8.900%
Expectancy
0.065
Net Profit
53.480%
Sharpe Ratio
0.955
Loss Rate
47%
Win Rate
53%
Profit-Loss Ratio
1.02
Alpha
0.065
Beta
-0.27
Annual Standard Deviation
0.075
Annual Variance
0.006
Information Ratio
0.722
Tracking Error
0.132
Treynor Ratio
-0.265
Total Fees
$0.00
namespace QuantConnect 
{   
	/*
	Notes to peer review:
	Quantpedia said to backtest assumming a 1pip spread.
	I wrote a slippage model for that. It takes a multiplier to the minimum price variation (pipette):
	    Securities[symbol].SlippageModel = new PipetteSlippageModel(this, multiple);
	when multiple is 10, it represents a pip (10 times the pipette). 
	With that setup, the strategy is not profitable (-8.90 return). 
	To meet Quantpedia indicative performance of 6.60%, we need to set multiple to 7 (70% of a pip).
	*/
	
    /*
	Academic paper states that the exporters, being large traders in the foreign exchange market,
	induce systematic pattern in the intraday dynamics of exchange rates.
	Currency market is segmented in the time dimension: When the American exporters are trading
	in their business hours, the European exporters are sleeping. Due to the segmentation of 
	business hours, exporters face insufficient interest from the buying side. They thus need
	the help of financial intermediaries to transfer the currencies from day to night. 
	The intermediaries require a risk premium for being exposed to the exchange rate risk, 
	so foreign currencies appreciate during home business hours.
	
	Simple trading strategy
	The investment universe consists of EUR/USD currency pair. 
	Each day, investor goes short EUR/USD during EU business hours (from 8 AM to 4 PM at London time)
	and goes long EUR/USD during US business hours (from 4 PM London time to 5 PM New York time) 
	and respectively. Transaction bid/ask spread is assumed 1pip and is deducted from presented 
	performance.
	
	Source Paper
	Jiang: Currency Returns in Different Time Zones
	http://papers.ssrn.com/sol3/papers.cfm?abstract_id=2613592
    */
    public class IntradayCurrencySeasonality : QCAlgorithm
    {
    	private int multiple = 0;
    	private Symbol symbol = QuantConnect.Symbol.Create("EURUSD", SecurityType.Forex, Market.Oanda);
    	
    	public long Quantity { get { return Securities[symbol].Holdings.Quantity; }	}
    	
    	public DateTime LondonDateTime { get { return Time.ConvertTo(TimeZones.EasternStandard, TimeZones.London); } }
    	
    	public DateTime NewYorkDateTime { get {	return Time.ConvertTo(TimeZones.EasternStandard, TimeZones.NewYork); } }
    	
    	public bool IsUsExchangeOpen
    	{
    		get
    		{
    			return 
    				LondonDateTime.TimeOfDay >= new TimeSpan(16, 00, 00) &&
    				NewYorkDateTime.TimeOfDay < new TimeSpan(16, 59, 00);
    		}
    	}
    	
    	public bool IsEuExchangeOpen
    	{
    		get
    		{
    			return 
    				LondonDateTime.TimeOfDay >= new TimeSpan(8, 00, 00) &&
    				LondonDateTime.TimeOfDay < new TimeSpan(16, 00, 00);
    		}
    	}
    	
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize() 
        {
            //Start and End Date range for the backtest:
            SetStartDate(2010, 1, 1);         
            SetEndDate(2015, 1, 1);
            
            //Cash allocation
            SetCash(25000);
            
            SetBenchmark(symbol);
            SetBrokerageModel(BrokerageName.OandaBrokerage);
            
            //Add as many securities as you like. All the data will be passed into the event handler:
            AddSecurity(symbol.ID.SecurityType, symbol, Resolution.Minute);
            
            // x pipette slippage model
            Securities[symbol].SlippageModel = new PipetteSlippageModel(this, multiple);
        }

        //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)
        {   
        	if(IsEuExchangeOpen && Quantity >= 0)
            {
            	SetHoldings(symbol, -1);
            	Log("SHORT: " + LondonDateTime.ToString("yyyy-MM-dd HH:mm") + " (London Time)");
            }
            
            if(IsUsExchangeOpen && Quantity <= 0)
            {
            	SetHoldings(symbol, 1);	
            	Log("LONG:  " + LondonDateTime.ToString("yyyy-MM-dd HH:mm") + " (London Time)");
            	Log("       " + NewYorkDateTime.ToString("           HH:mm") + " (New York Time)");
            }
            
            if(!IsUsExchangeOpen && !IsEuExchangeOpen && Quantity != 0)
            {
            	Liquidate(symbol);
            	Log("FLAT:  " + NewYorkDateTime.ToString("yyyy-MM-dd HH:mm") + " (New York Time)");
            }
        }
    }
}
namespace QuantConnect {
	
	public class PipetteSlippageModel : ISlippageModel
  	{
    	private readonly int _size;
        private readonly IAlgorithm _algorithm;

        public PipetteSlippageModel(IAlgorithm algorithm, int size)
        {
        	_size = size;
        	_algorithm = algorithm;
        }

        public decimal GetSlippageApproximation(Security asset, Order order)
        {
        	if(_size <= 0) return 0;
        	
            var pipette = asset.SymbolProperties.MinimumPriceVariation;
            var slippage = asset.Price * _size * pipette;
                
            _algorithm.Log("PipetteSlippageModel: " + slippage);
            return slippage;
        }
    }
}