/// <summary> /// Event handler for streaming ticks /// </summary> /// <param name="data">The data object containing the received tick</param> private void OnDataReceived(RateStreamResponse data) { if (data.IsHeartbeat()) { PricingConnectionHandler.KeepAlive(DateTime.UtcNow); return; } if (data.tick == null) { return; } var securityType = SymbolMapper.GetBrokerageSecurityType(data.tick.instrument); var symbol = SymbolMapper.GetLeanSymbol(data.tick.instrument, securityType, Market.Oanda); var time = OandaBrokerage.GetDateTimeFromString(data.tick.time); // live ticks timestamps must be in exchange time zone DateTimeZone exchangeTimeZone; if (!_symbolExchangeTimeZones.TryGetValue(symbol, out exchangeTimeZone)) { exchangeTimeZone = MarketHoursDatabase.FromDataFolder().GetExchangeHours(Market.Oanda, symbol, securityType).TimeZone; _symbolExchangeTimeZones.Add(symbol, exchangeTimeZone); } time = time.ConvertFromUtc(exchangeTimeZone); var bidPrice = Convert.ToDecimal(data.tick.bid); var askPrice = Convert.ToDecimal(data.tick.ask); var tick = new Tick(time, symbol, bidPrice, askPrice); EmitTick(tick); }
/// <summary> /// Creates the brokerage under test and connects it /// </summary> /// <returns>A connected brokerage instance</returns> protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, IHoldingsProvider holdingsProvider) { var oandaBrokerage = new OandaBrokerage(orderProvider, 0); var tokens = OandaBrokerageFactory.GetTokens(); var environment = Config.Get("oanda-environment"); if (environment == "sandbox") { var requestString = EndpointResolver.ResolveEndpoint(Environment.Sandbox, Server.Account) + "accounts"; var accountResponse = oandaBrokerage.MakeRequest<AccountResponse>(requestString, "POST"); oandaBrokerage.SetAccountId(accountResponse.accountId); oandaBrokerage.SetEnvironment("sandbox"); oandaBrokerage.SetUserName(accountResponse.username); } else { oandaBrokerage.SetAccountId(Convert.ToInt32(Config.Get("oanda-account-id"))); oandaBrokerage.SetEnvironment(Config.Get("oanda-environment")); } var qcUserId = OandaBrokerageFactory.Configuration.QuantConnectUserId; oandaBrokerage.SetTokens(qcUserId, tokens.AccessToken, tokens.IssuedAt, TimeSpan.FromSeconds(tokens.ExpiresIn)); oandaBrokerage.InitializeInstrumentSecurityTypeMap(); // keep the tokens up to date in the event of a refresh oandaBrokerage.SessionRefreshed += (sender, args) => { File.WriteAllText(OandaBrokerageFactory.TokensFile, JsonConvert.SerializeObject(args, Formatting.Indented)); }; return oandaBrokerage; }
/// <summary> /// Downloads a list of TradeBars at the requested resolution /// </summary> /// <param name="symbol">The symbol</param> /// <param name="startTimeUtc">The starting time (UTC)</param> /// <param name="endTimeUtc">The ending time (UTC)</param> /// <param name="resolution">The requested resolution</param> /// <param name="requestedTimeZone">The requested timezone for the data</param> /// <returns>The list of bars</returns> public override IEnumerable <TradeBar> DownloadTradeBars(Symbol symbol, DateTime startTimeUtc, DateTime endTimeUtc, Resolution resolution, DateTimeZone requestedTimeZone) { var oandaSymbol = SymbolMapper.GetBrokerageSymbol(symbol); var startUtc = startTimeUtc.ToString("yyyy-MM-ddTHH:mm:ssZ"); var candles = GetCandles(oandaSymbol, startUtc, OandaBrokerage.MaxBarsPerRequest, resolution, ECandleFormat.midpoint); foreach (var candle in candles) { var time = OandaBrokerage.GetDateTimeFromString(candle.time); if (time > endTimeUtc) { break; } yield return(new TradeBar( time.ConvertFromUtc(requestedTimeZone), symbol, Convert.ToDecimal(candle.openMid), Convert.ToDecimal(candle.highMid), Convert.ToDecimal(candle.lowMid), Convert.ToDecimal(candle.closeMid), 0, resolution.ToTimeSpan())); } }
/// <summary> /// Creates a new <see cref="IBrokerage"/> instance /// </summary> /// <param name="job">The job packet to create the brokerage for</param> /// <param name="algorithm">The algorithm instance</param> /// <returns>A new brokerage instance</returns> public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm) { var errors = new List <string>(); // read values from the brokerage data var environment = Read <Environment>(job.BrokerageData, "oanda-environment", errors); var accessToken = Read <string>(job.BrokerageData, "oanda-access-token", errors); var accountId = Read <string>(job.BrokerageData, "oanda-account-id", errors); var agent = Read <string>(job.BrokerageData, "oanda-agent", errors); if (errors.Count != 0) { // if we had errors then we can't create the instance throw new Exception(string.Join(System.Environment.NewLine, errors)); } var brokerage = new OandaBrokerage( algorithm.Transactions, algorithm.Portfolio, Composer.Instance.GetExportedValueByTypeName <IDataAggregator>(Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager"), forceTypeNameOnExisting: false), environment, accessToken, accountId, agent); Composer.Instance.AddPart <IDataQueueHandler>(brokerage); return(brokerage); }
public void GetsHistory(Symbol symbol, Resolution resolution, TimeSpan period, bool throwsException) { TestDelegate test = () => { var environment = Config.Get("oanda-environment").ConvertTo<Environment>(); var accessToken = Config.Get("oanda-access-token"); var accountId = Config.Get("oanda-account-id"); var brokerage = new OandaBrokerage(null, null, environment, accessToken, accountId); var now = DateTime.UtcNow; var requests = new[] { new HistoryRequest { Symbol = symbol, Resolution = resolution, StartTimeUtc = now.Add(-period), EndTimeUtc = now } }; var history = brokerage.GetHistory(requests, TimeZones.Utc); foreach (var slice in history) { if (resolution == Resolution.Tick) { foreach (var tick in slice.Ticks[symbol]) { Log.Trace("{0}: {1} - {2} / {3}", tick.Time, tick.Symbol, tick.BidPrice, tick.AskPrice); } } else { var bar = slice.Bars[symbol]; Log.Trace("{0}: {1} - O={2}, H={3}, L={4}, C={5}", bar.Time, bar.Symbol, bar.Open, bar.High, bar.Low, bar.Close); } } Log.Trace("Data points retrieved: " + brokerage.DataPointCount); }; if (throwsException) { Assert.Throws<ArgumentException>(test); } else { Assert.DoesNotThrow(test); } }
/// <summary> /// Creates a new <see cref="IBrokerage"/> instance /// </summary> /// <param name="job">The job packet to create the brokerage for</param> /// <param name="algorithm">The algorithm instance</param> /// <returns>A new brokerage instance</returns> public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm) { var errors = new List <string>(); // read values from the brokerage data var environment = Read <Environment>(job.BrokerageData, "oanda-environment", errors); var accessToken = Read <string>(job.BrokerageData, "oanda-access-token", errors); var accountId = Read <string>(job.BrokerageData, "oanda-account-id", errors); if (errors.Count != 0) { // if we had errors then we can't create the instance throw new Exception(string.Join(System.Environment.NewLine, errors)); } var brokerage = new OandaBrokerage(algorithm.Transactions, algorithm.Portfolio, environment, accessToken, accountId); Composer.Instance.AddPart <IDataQueueHandler>(brokerage); return(brokerage); }
/// <summary> /// Downloads a list of QuoteBars at the requested resolution /// </summary> /// <param name="symbol">The symbol</param> /// <param name="startTimeUtc">The starting time (UTC)</param> /// <param name="endTimeUtc">The ending time (UTC)</param> /// <param name="resolution">The requested resolution</param> /// <param name="requestedTimeZone">The requested timezone for the data</param> /// <returns>The list of bars</returns> public override IEnumerable <QuoteBar> DownloadQuoteBars(Symbol symbol, DateTime startTimeUtc, DateTime endTimeUtc, Resolution resolution, DateTimeZone requestedTimeZone) { var oandaSymbol = SymbolMapper.GetBrokerageSymbol(symbol); var startUtc = startTimeUtc.ToString("yyyy-MM-ddTHH:mm:ssZ"); // Oanda only has 5-second bars, we return these for Resolution.Second var period = resolution == Resolution.Second ? TimeSpan.FromSeconds(5) : resolution.ToTimeSpan(); var candles = GetCandles(oandaSymbol, startUtc, OandaBrokerage.MaxBarsPerRequest, resolution, ECandleFormat.bidask); foreach (var candle in candles) { var time = OandaBrokerage.GetDateTimeFromString(candle.time); if (time > endTimeUtc) { break; } yield return(new QuoteBar( time.ConvertFromUtc(requestedTimeZone), symbol, new Bar( Convert.ToDecimal(candle.openBid), Convert.ToDecimal(candle.highBid), Convert.ToDecimal(candle.lowBid), Convert.ToDecimal(candle.closeBid) ), 0, new Bar( Convert.ToDecimal(candle.openAsk), Convert.ToDecimal(candle.highAsk), Convert.ToDecimal(candle.lowAsk), Convert.ToDecimal(candle.closeAsk) ), 0, period)); } }
/// <summary> /// Creates a new IBrokerage instance /// </summary> /// <param name="job">The job packet to create the brokerage for</param> /// <param name="algorithm">The algorithm instance</param> /// <returns>A new brokerage instance</returns> public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm) { var errors = new List <string>(); var accountId = Read <int>(job.BrokerageData, "oanda-account-id", errors); var accessToken = Read <string>(job.BrokerageData, "oanda-access-token", errors); var issuedAt = Read <DateTime>(job.BrokerageData, "oanda-issued-at", errors); var lifeSpan = TimeSpan.FromSeconds(Read <double>(job.BrokerageData, "oanda-lifespan", errors)); var environment = Read <string>(job.BrokerageData, "oanda-environment", errors); var brokerage = new OandaBrokerage(algorithm.Transactions, accountId); // if we're running live locally we'll want to save any new tokens generated so that they can easily be retrieved if (Config.GetBool("local")) { brokerage.SessionRefreshed += (sender, args) => { File.WriteAllText(TokensFile, JsonConvert.SerializeObject(args, Formatting.Indented)); }; } brokerage.SetTokens(job.UserId, accessToken, issuedAt, lifeSpan); brokerage.SetEnvironment(environment); return(brokerage); }
/// <summary> /// Returns a DateTime from an RFC3339 string (with high resolution) /// </summary> /// <param name="time">The time string</param> private static DateTime GetTickDateTimeFromString(string time) { // remove nanoseconds, DateTime.ParseExact will throw with 9 digits after seconds return(OandaBrokerage.GetDateTimeFromString(time.Remove(25, 3))); }
/// <summary> /// Creates a new <see cref="IBrokerage"/> instance /// </summary> /// <param name="job">The job packet to create the brokerage for</param> /// <param name="algorithm">The algorithm instance</param> /// <returns>A new brokerage instance</returns> public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm) { var errors = new List<string>(); // read values from the brokerage data var environment = Read<Environment>(job.BrokerageData, "oanda-environment", errors); var accessToken = Read<string>(job.BrokerageData, "oanda-access-token", errors); var accountId = Read<int>(job.BrokerageData, "oanda-account-id", errors); if (errors.Count != 0) { // if we had errors then we can't create the instance throw new Exception(string.Join(System.Environment.NewLine, errors)); } var brokerage = new OandaBrokerage(algorithm.Transactions, algorithm.Portfolio, environment, accessToken, accountId); Composer.Instance.AddPart<IDataQueueHandler>(brokerage); return brokerage; }
/// <summary> /// Creates a new IBrokerage instance /// </summary> /// <param name="job">The job packet to create the brokerage for</param> /// <param name="algorithm">The algorithm instance</param> /// <returns>A new brokerage instance</returns> public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm) { var errors = new List<string>(); var accountId = Read<int>(job.BrokerageData, "oanda-account-id", errors); var accessToken = Read<string>(job.BrokerageData, "oanda-access-token", errors); var issuedAt = Read<DateTime>(job.BrokerageData, "oanda-issued-at", errors); var lifeSpan = TimeSpan.FromSeconds(Read<double>(job.BrokerageData, "oanda-lifespan", errors)); var environment = Read<string>(job.BrokerageData, "oanda-environment", errors); var brokerage = new OandaBrokerage(algorithm.Transactions, accountId); // if we're running live locally we'll want to save any new tokens generated so that they can easily be retrieved if (Config.GetBool("local")) { brokerage.SessionRefreshed += (sender, args) => { File.WriteAllText(TokensFile, JsonConvert.SerializeObject(args, Formatting.Indented)); }; } brokerage.SetTokens(job.UserId, accessToken, issuedAt, lifeSpan); brokerage.SetEnvironment(environment); return brokerage; }
/// <summary> /// Initializes a new instance of the <see cref="OandaDataDownloader"/> class /// </summary> public OandaDataDownloader(string accessToken, string accountId) { // Set Oanda account credentials _brokerage = new OandaBrokerage(null, null, Environment.Practice, accessToken, accountId); }