Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Reactive Oanda API wrapper for Scala based on akka-streams and akka-http.

License

Notifications You must be signed in to change notification settings

MartinSeeler/rx-oanda

Repository files navigation

banner

Travis CI codecov.io Codacy Gitter Apache License

Environments

Oanda provides two different API environments for you, depending on whether you want to use real or fake money.

No matter which one you choose, you need to specifiy the API token for your account, since all endpoints require authentication. To obtain your personal token, go to My Account -> My Services -> Manage API Access. From there, you can generate a personal access token to use with the Oanda API, as well as revoke a token you may currently have.

Both environments can be found in the following package:

import rx.oanda.OandaEnvironment._

The fxTrade Practice environment is used for practicing, as the name suggests. It's a fake money copy of the fxTrade environment, which means that the market data you receive is real, but the money is not. Use this environment to develop your trading robots / strategies / whatever, before you risk your real money.

val practiceEnv = TradePracticeEnvironment("your-token")
// practiceEnv: rx.oanda.OandaEnvironment = OandaEnvironment(fxTrade Practice,api-fxpractice.oanda.com,stream-fxpractice.oanda.com,your-token)

When you're ready to risk your money and you feel comfortable enough, go ahead and use the fxTrade environment. But keep in mind: you're trading with real money here!

val tradeEnv = TradeEnvironment("your-token")
// tradeEnv: rx.oanda.OandaEnvironment = OandaEnvironment(fxTrade,api-fxtrade.oanda.com,stream-fxtrade.oanda.com,your-token)

The clients will get the environments as arguments, so they know which endpoints to use. This makes it easy to switch between both environments or to get your strategy ready for real money trading.

Instruments and Prices

The RatesClient provides access to tradable instruments and prices. To get started, we have to create a new instance with our environment.

import rx.oanda.rates._
// import rx.oanda.rates._

val ratesClient = new RatesClient(practiceEnv)
// ratesClient: rx.oanda.rates.RatesClient = rx.oanda.rates.RatesClient@10b7b517

Instruments

An Instrument is either a currency pair, a CFD or a commodity. To get all instruments which are available with our account, we can call allInstruments with our account id to get a Source[Instrument, NotUsed], which emits all instruments one by one. Keep in mind that the request itself is executed lazily when we actually run our source connected as graph.

ratesClient.allInstruments(accountId)
// res0: akka.stream.scaladsl.Source[rx.oanda.instruments.Instrument,akka.NotUsed] = akka.stream.scaladsl.Source@332d4686

If we're only interested in specific instruments, there are some more methods available.

ratesClient.instruments(accountId, List("EUR_USD", "EUR_GBP", "GBP_USD"))
// res1: akka.stream.scaladsl.Source[rx.oanda.instruments.Instrument,akka.NotUsed] = akka.stream.scaladsl.Source@49f148be

ratesClient.instrument(accountId, "EUR_USD")
// res2: akka.stream.scaladsl.Source[rx.oanda.instruments.Instrument,akka.NotUsed] = akka.stream.scaladsl.Source@7812324e

Most of the other methods (also in other clients) will require an instrument code, which can be found at the instrument's field instrument.

Prices

To get the latest price for one or more instruments from Oanda, we can use the price or prices methods, which will emit the latest known price per instrument as instance of a Price and then finishes.

ratesClient.prices(List("EUR_USD", "EUR_GBP", "GBP_USD"))
// res3: akka.stream.scaladsl.Source[rx.oanda.rates.Price,akka.NotUsed] = akka.stream.scaladsl.Source@381c048d

ratesClient.price("EUR_USD")
// res4: akka.stream.scaladsl.Source[rx.oanda.rates.Price,akka.NotUsed] = akka.stream.scaladsl.Source@677e8851

Another option to receive prices for instruments is to stream them continuously, which is handy if we want to trade on a per tick base.

ratesClient.livePrices(accountId, List("EUR_USD", "GBP_USD"))
// res5: akka.stream.scaladsl.Source[cats.data.Xor[rx.oanda.rates.Price,rx.oanda.utils.Heartbeat],akka.NotUsed] = akka.stream.scaladsl.Source@4e8d5396

As we can see, the resulting return type is cats.data.Xor[Price, Heartbeat]. The Heartbeats are provided by Oanda to keep the connection alive. This is useful to monitor the connection and restart it, when nothing was received for 10 seconds or more (more about it in their documentation here and here).

If you are only interested in the prices and want to ignore the heartbeats, here is what you wanna use

ratesClient.livePrices(accountId, List("EUR_USD", "GBP_USD")).flatMapConcat {
  case cats.data.Xor.Left(price)  Source.single(price)
  case cats.data.Xor.Right(heartbeat)  Source.empty
}
// res6: akka.stream.scaladsl.Source[rx.oanda.rates.Price,akka.NotUsed] = akka.stream.scaladsl.Source@bcc7a93

It is also possible to define a session id, since Oanda will disconnect all other streaming connections if there are more than two currently open. By providing a session id, only the other open connection with the same id will be closed.

ratesClient.livePrices(accountId, List("EUR_USD", "GBP_USD"), sessionId = Some("session-42"))
// res7: akka.stream.scaladsl.Source[cats.data.Xor[rx.oanda.rates.Price,rx.oanda.utils.Heartbeat],akka.NotUsed] = akka.stream.scaladsl.Source@c76bbd1

The following is another example, how to stream prices for all instruments.

ratesClient.allInstruments(accountId).
    map(_.instrument).
    fold(Vector.empty[String])(_ :+ _).
    flatMapConcat(ratesClient.livePrices(accountId, _)).
    flatMapConcat {
      case Xor.Left(price)  Source.single(price)
      case Xor.Right(heartbeat)  Source.empty
    }
// res8: akka.stream.scaladsl.Source[rx.oanda.rates.Price,akka.NotUsed] = akka.stream.scaladsl.Source@417a4070

About

Reactive Oanda API wrapper for Scala based on akka-streams and akka-http.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published