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