From 34e7c1bb0ba387847975d3515f87bf0744a05080 Mon Sep 17 00:00:00 2001 From: Yuri Kovalov Date: Mon, 5 Sep 2022 22:29:34 +0800 Subject: [PATCH] Convert bitmex product types --- .../lib/tai/venue_adapters/bitmex/product.ex | 5 +-- .../tai/venue_adapters/bitmex/product_type.ex | 31 +++++++++++++++++++ .../venue_adapters/bitmex/product_test.exs | 20 ++---------- .../bitmex/product_type_test.exs | 13 ++++++++ .../tai/venues/adapters/products_test.exs | 3 ++ 5 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 apps/tai/lib/tai/venue_adapters/bitmex/product_type.ex create mode 100644 apps/tai/test/tai/venue_adapters/bitmex/product_type_test.exs diff --git a/apps/tai/lib/tai/venue_adapters/bitmex/product.ex b/apps/tai/lib/tai/venue_adapters/bitmex/product.ex index 75d619819..b08ca0ab2 100644 --- a/apps/tai/lib/tai/venue_adapters/bitmex/product.ex +++ b/apps/tai/lib/tai/venue_adapters/bitmex/product.ex @@ -5,7 +5,7 @@ defmodule Tai.VenueAdapters.Bitmex.Product do def build(instrument, venue_id) do symbol = instrument.symbol |> downcase_and_atom - type = instrument.expiry |> type() + type = Tai.VenueAdapters.Bitmex.ProductType.normalize(instrument.typ) status = Tai.VenueAdapters.Bitmex.ProductStatus.normalize(instrument.state) listing = instrument.listing && Timex.parse!(instrument.listing, @format) expiry = instrument.expiry && Timex.parse!(instrument.expiry, @format) @@ -45,7 +45,4 @@ defmodule Tai.VenueAdapters.Bitmex.Product do end def downcase_and_atom(str), do: str |> String.downcase() |> String.to_atom() - - defp type(nil), do: :swap - defp type(_), do: :future end diff --git a/apps/tai/lib/tai/venue_adapters/bitmex/product_type.ex b/apps/tai/lib/tai/venue_adapters/bitmex/product_type.ex new file mode 100644 index 000000000..9700013dd --- /dev/null +++ b/apps/tai/lib/tai/venue_adapters/bitmex/product_type.ex @@ -0,0 +1,31 @@ +defmodule Tai.VenueAdapters.Bitmex.ProductType do + @type type :: Tai.Venues.Product.type() + + @doc """ + Maps Bitmex product types to Tai product types. + + https://www.bitmex.com/api/explorer/#!/Instrument/Instrument_get + + Perpetual Contracts - FFWCSX + Perpetual Contracts (FX underliers) - FFWCSF + Spot - IFXXXP + Futures - FFCCSX + BitMEX Basket Index - MRBXXX + BitMEX Crypto Index - MRCXXX + BitMEX FX Index - MRFXXX + BitMEX Lending/Premium Index - MRRXXX + BitMEX Volatility Index - MRIXXX + + ## Examples + + iex> Tai.VenueAdapters.Bitmex.ProductType.normalize("FFWCSX") + :swap + + """ + + @spec normalize(bitmex_product_type :: String.t()) :: type + def normalize("FFWCS" <> _), do: :swap # FFWCSX, FFWCSF + def normalize("FFCCS" <> _), do: :future # FFCCSX + def normalize("IF" <> _), do: :spot # IFXXXP + def normalize(_), do: :future +end diff --git a/apps/tai/test/tai/venue_adapters/bitmex/product_test.exs b/apps/tai/test/tai/venue_adapters/bitmex/product_test.exs index 1f139b35b..d3490a0e8 100644 --- a/apps/tai/test/tai/venue_adapters/bitmex/product_test.exs +++ b/apps/tai/test/tai/venue_adapters/bitmex/product_test.exs @@ -17,7 +17,8 @@ defmodule Tai.VenuesAdapters.Bitmex.ProductTest do quote_currency: "USD", state: "Open", lot_size: 1, - tick_size: 0.5 + tick_size: 0.5, + typ: "FFWCSX" } test "returns a product struct from a venue instrument" do @@ -28,28 +29,13 @@ defmodule Tai.VenuesAdapters.Bitmex.ProductTest do assert product.symbol == :xbtusd assert product.venue_symbol == "XBTUSD" assert product.status == :trading + assert product.type == :swap assert product.price_increment == Decimal.new("0.5") assert product.min_price == Decimal.new("0.5") assert product.size_increment == Decimal.new(1) assert product.value == Decimal.new(1) end - test "type is :future when there is an expiry" do - attrs = Map.merge(@base_attrs, %{expiry: "2020-06-26T12:00:00.000Z"}) - instrument = struct(ExBitmex.Instrument, attrs) - - product = Tai.VenueAdapters.Bitmex.Product.build(instrument, :venue_a) - assert product.type == :future - end - - test "type is :swap when there is no expiry" do - attrs = Map.merge(@base_attrs, %{expiry: nil}) - instrument = struct(ExBitmex.Instrument, attrs) - - product = Tai.VenueAdapters.Bitmex.Product.build(instrument, :venue_a) - assert product.type == :swap - end - test "assigns maker/taker fee when present" do attrs = Map.merge(@base_attrs, %{maker_fee: "-0.025", taker_fee: "0.05"}) instrument = struct(ExBitmex.Instrument, attrs) diff --git a/apps/tai/test/tai/venue_adapters/bitmex/product_type_test.exs b/apps/tai/test/tai/venue_adapters/bitmex/product_type_test.exs new file mode 100644 index 000000000..6157159f1 --- /dev/null +++ b/apps/tai/test/tai/venue_adapters/bitmex/product_type_test.exs @@ -0,0 +1,13 @@ +defmodule Tai.VenueAdapters.Bitmex.ProductTypeTest do + use ExUnit.Case, async: true + alias Tai.VenueAdapters.Bitmex + + test ".normalize/1 converts product type" do + assert Bitmex.ProductType.normalize("FFWCSX") == :swap + assert Bitmex.ProductType.normalize("FFWCSF") == :swap + assert Bitmex.ProductType.normalize("IFXXXP") == :spot + assert Bitmex.ProductType.normalize("FFCCSX") == :future + + assert Bitmex.ProductType.normalize("XXXXXX") == :future, "fallback to future" + end +end diff --git a/apps/tai/test/tai/venues/adapters/products_test.exs b/apps/tai/test/tai/venues/adapters/products_test.exs index 0fac65422..de17aa345 100644 --- a/apps/tai/test/tai/venues/adapters/products_test.exs +++ b/apps/tai/test/tai/venues/adapters/products_test.exs @@ -30,6 +30,7 @@ defmodule Tai.Venues.Adapters.ProductsTest do assert product.venue_id == @venue.id assert product.symbol != nil assert product.status != nil + assert product.type != nil assert %Decimal{} = product.min_size assert %Decimal{} = product.min_price assert %Decimal{} = product.size_increment @@ -50,6 +51,7 @@ defmodule Tai.Venues.Adapters.ProductsTest do min_price: Decimal.new("0.01"), size_increment: Decimal.new("0.001"), price_increment: Decimal.new("0.01"), + type: :spot }, %{ symbol: :ltc_usd, @@ -59,6 +61,7 @@ defmodule Tai.Venues.Adapters.ProductsTest do min_price: Decimal.new("0.01"), size_increment: Decimal.new("0.001"), price_increment: Decimal.new("0.01"), + type: :spot } ] )