From a660179ee84185801047f90deef9eb7285dc5a63 Mon Sep 17 00:00:00 2001 From: Daniel Sienkiewicz Date: Tue, 5 Dec 2023 11:25:05 +0100 Subject: [PATCH] Fix decoding balance message --- lib/xtb_client/connection.ex | 3 +- lib/xtb_client/messages/balance_info.ex | 47 +++++++++++++++++---- test/xtb_client/connection_test.exs | 50 ++++++++++++++++------- test/xtb_client/main_socket_test.exs | 3 +- test/xtb_client/streaming_socket_test.exs | 2 +- 5 files changed, 78 insertions(+), 27 deletions(-) diff --git a/lib/xtb_client/connection.ex b/lib/xtb_client/connection.ex index 9f665af..2ea4d05 100644 --- a/lib/xtb_client/connection.ex +++ b/lib/xtb_client/connection.ex @@ -118,12 +118,11 @@ defmodule XtbClient.Connection do @impl true def init(opts) do {:ok, mpid} = MainSocket.start_link(opts) + Process.flag(:trap_exit, true) Process.sleep(500) MainSocket.stream_session_id(mpid, self()) - Process.flag(:trap_exit, true) - type = get_in(opts, [:type]) url = get_in(opts, [:url]) diff --git a/lib/xtb_client/messages/balance_info.ex b/lib/xtb_client/messages/balance_info.ex index b84e5bb..6db5ef6 100644 --- a/lib/xtb_client/messages/balance_info.ex +++ b/lib/xtb_client/messages/balance_info.ex @@ -24,7 +24,7 @@ defmodule XtbClient.Messages.BalanceInfo do balance: float(), cash_stock_value: float(), credit: float(), - currency: String.t(), + currency: String.t() | nil, equity: float(), equity_fx: float(), margin: float(), @@ -51,7 +51,7 @@ defmodule XtbClient.Messages.BalanceInfo do defstruct balance: 0.0, cash_stock_value: 0.0, credit: 0.0, - currency: "", + currency: nil, equity: 0.0, equity_fx: 0.0, margin: 0.0, @@ -60,33 +60,62 @@ defmodule XtbClient.Messages.BalanceInfo do stock_lock: 0.0, stock_value: 0.0 + def new(%{"currency" => currency} = args) do + value = args |> Map.drop(["currency"]) |> new() + + %{value | currency: currency || ""} + end + + def new( + %{ + "margin_free" => margin_free, + "margin_level" => margin_level + } = args + ) + when is_number(margin_free) and is_number(margin_level) do + value = args |> Map.drop(["margin_free", "margin_level"]) |> new() + + %{value | margin_free: margin_free, margin_level: margin_level} + end + + def new( + %{ + "marginFree" => margin_free, + "marginLevel" => margin_level + } = args + ) + when is_number(margin_free) and is_number(margin_level) do + args + |> Map.drop(["marginFree", "marginLevel"]) + |> Map.put("margin_free", margin_free) + |> Map.put("margin_level", margin_level) + |> new() + end + def new(%{ "balance" => balance, "cashStockValue" => cash_stock_value, "credit" => credit, - "currency" => currency, "equity" => equity, "equityFX" => equity_fx, "margin" => margin, - "margin_free" => margin_free, - "margin_level" => margin_level, "stockLock" => stock_lock, "stockValue" => stock_value }) when is_number(balance) and is_number(cash_stock_value) and is_number(credit) and is_number(equity) and is_number(equity_fx) and - is_number(margin) and is_number(margin_free) and is_number(margin_level) and + is_number(margin) and is_number(stock_lock) and is_number(stock_value) do %__MODULE__{ balance: balance, cash_stock_value: cash_stock_value, credit: credit, - currency: currency || "", + currency: nil, equity: equity, equity_fx: equity_fx, margin: margin, - margin_free: margin_free, - margin_level: margin_level, + margin_free: 0.0, + margin_level: 0.0, stock_lock: stock_lock, stock_value: stock_value } diff --git a/test/xtb_client/connection_test.exs b/test/xtb_client/connection_test.exs index 65814a3..b75009c 100644 --- a/test/xtb_client/connection_test.exs +++ b/test/xtb_client/connection_test.exs @@ -1,6 +1,6 @@ defmodule XtbClient.ConnectionTest do @moduledoc false - use ExUnit.Case, async: true + use ExUnit.Case doctest XtbClient.Connection alias XtbClient.Connection @@ -99,9 +99,11 @@ defmodule XtbClient.ConnectionTest do end test "get chart last", %{pid: pid} do + now = DateTime.utc_now() + args = %{ period: :h1, - start: DateTime.utc_now() |> DateTime.add(-30 * 24 * 60 * 60), + start: DateTime.add(now, -30 * 24 * 60 * 60), symbol: "EURPLN" } @@ -111,7 +113,28 @@ defmodule XtbClient.ConnectionTest do assert %RateInfos{} = result assert is_number(result.digits) assert [elem | _] = result.data - assert %Candle{} = elem + + assert %Candle{ + symbol: symbol, + open: open, + high: high, + low: low, + close: close, + vol: vol, + ctm: ctm, + ctm_string: ctm_string, + quote_id: quote_id + } = elem + + assert "EURPLN" == symbol + assert is_number(open) + assert is_number(high) + assert is_number(low) + assert is_number(close) + assert is_number(vol) + assert DateTime.compare(ctm, now) == :lt + assert is_binary(ctm_string) + refute quote_id end test "get chart range", %{pid: pid} do @@ -287,6 +310,9 @@ defmodule XtbClient.ConnectionTest do end test "trade transaction - open and close transaction", %{pid: pid} do + # needed to wait for message to be received from server that transaction is accepted + Connection.subscribe_get_trade_status(pid, self()) + buy_args = %{ operation: :buy, custom_comment: "Buy transaction", @@ -301,8 +327,7 @@ defmodule XtbClient.ConnectionTest do assert %TradeTransaction{} = result - # needs some time for server to process order correctly - Process.sleep(100) + assert_receive {:ok, %TradeStatus{}}, @default_wait_time open_order_id = result.order status = TradeTransactionStatus.Query.new(open_order_id) @@ -310,9 +335,6 @@ defmodule XtbClient.ConnectionTest do assert %TradeTransactionStatus{} = result - # needs some time for server to process order correctly - Process.sleep(100) - # get all opened only trades trades_query = Trades.Query.new(true) result = Connection.get_trades(pid, trades_query) @@ -337,6 +359,7 @@ defmodule XtbClient.ConnectionTest do result = Connection.trade_transaction(pid, close) assert %TradeTransaction{} = result + assert_receive {:ok, %TradeStatus{}}, @default_wait_time close_order_id = result.order status = TradeTransactionStatus.Query.new(close_order_id) @@ -346,6 +369,8 @@ defmodule XtbClient.ConnectionTest do end test "subscribe to get balance", %{pid: pid} do + Connection.subscribe_get_balance(pid, self()) + buy_args = %{ operation: :buy, custom_comment: "Buy transaction", @@ -361,11 +386,7 @@ defmodule XtbClient.ConnectionTest do assert %TradeTransaction{} = result open_order_id = result.order - # needs some time for server to process order correctly - Process.sleep(100) - - # real test scenario - Connection.subscribe_get_balance(pid, self()) + assert_receive {:ok, %BalanceInfo{}}, @default_wait_time # get all opened only trades trades_query = Trades.Query.new(true) @@ -389,8 +410,9 @@ defmodule XtbClient.ConnectionTest do close = TradeTransaction.Command.new(close_args) result = Connection.trade_transaction(pid, close) - assert %TradeTransaction{} = result + + assert_receive {:ok, %BalanceInfo{}}, @default_wait_time end @tag timeout: @default_wait_time diff --git a/test/xtb_client/main_socket_test.exs b/test/xtb_client/main_socket_test.exs index cac4ed0..be963d6 100644 --- a/test/xtb_client/main_socket_test.exs +++ b/test/xtb_client/main_socket_test.exs @@ -1,5 +1,6 @@ defmodule XtbClient.MainSocketTest do - use ExUnit.Case, async: true + @moduledoc false + use ExUnit.Case doctest XtbClient.MainSocket alias XtbClient.MainSocket diff --git a/test/xtb_client/streaming_socket_test.exs b/test/xtb_client/streaming_socket_test.exs index f6e189e..0471206 100644 --- a/test/xtb_client/streaming_socket_test.exs +++ b/test/xtb_client/streaming_socket_test.exs @@ -1,6 +1,6 @@ defmodule XtbClient.StreamingSocketTest do @moduledoc false - use ExUnit.Case, async: true + use ExUnit.Case doctest XtbClient.StreamingSocket alias XtbClient.MainSocket