From 48ba89a5554feccc1b75b1eb5f2416ab3b973965 Mon Sep 17 00:00:00 2001 From: Bodhert Date: Sat, 26 Apr 2025 22:45:31 -0500 Subject: [PATCH 1/2] test are working --- apps/indicator/lib/indicator/ohlc.ex | 3 +- apps/indicator/lib/indicator/ohlc/worker.ex | 7 +- apps/naive/lib/naive/strategy.ex | 24 ++-- apps/naive/lib/naive/trader.ex | 6 +- apps/naive/mix.exs | 10 +- apps/naive/test/naive/strategy_test.exs | 66 +++++++++++ apps/naive/test/naive/trader_test.exs | 122 ++++++++++---------- apps/naive/test/test_helper.exs | 13 +-- config/config.exs | 6 - config/test.exs | 9 -- mix.lock | 2 + notes/notes.md | 16 +++ 12 files changed, 169 insertions(+), 115 deletions(-) create mode 100644 apps/naive/test/naive/strategy_test.exs diff --git a/apps/indicator/lib/indicator/ohlc.ex b/apps/indicator/lib/indicator/ohlc.ex index 4920a91..8153fa8 100644 --- a/apps/indicator/lib/indicator/ohlc.ex +++ b/apps/indicator/lib/indicator/ohlc.ex @@ -2,7 +2,6 @@ defmodule Indicator.Ohlc do require Logger alias Core.Struct.TradeEvent - @pubsub_client Application.compile_env(:core, :pubsub_client) @enforce_keys [:symbol, :start_time, :duration] defstruct [:symbol, :start_time, :duration, :open, :high, :low, :close] @@ -71,7 +70,7 @@ defmodule Indicator.Ohlc do defp maybe_broadcast(%__MODULE__{} = ohlc) do Logger.debug("Broadcasting OHLC: #{inspect(ohlc)}") - @pubsub_client.broadcast( + Phoenix.PubSub.broadcast( Core.PubSub, "OHLC:#{ohlc.symbol}", ohlc diff --git a/apps/indicator/lib/indicator/ohlc/worker.ex b/apps/indicator/lib/indicator/ohlc/worker.ex index b80c83f..881ef6e 100644 --- a/apps/indicator/lib/indicator/ohlc/worker.ex +++ b/apps/indicator/lib/indicator/ohlc/worker.ex @@ -3,18 +3,15 @@ defmodule Indicator.Ohlc.Worker do require Logger alias Core.Struct.TradeEvent - @logger Application.compile_env(:core, :logger) - @pubsub_client Application.compile_env(:core, :pubsub_client) - def start_link(symbol) do GenServer.start_link(__MODULE__, symbol) end def init(symbol) do symbol = String.upcase(symbol) - @logger.debug("Initializing a new OHLC worker for #{symbol}") + Logger.debug("Initializing a new OHLC worker for #{symbol}") - @pubsub_client.subscribe( + Phoenix.PubSub.subscribe( Core.PubSub, "TRADE_EVENTS:#{symbol}" ) diff --git a/apps/naive/lib/naive/strategy.ex b/apps/naive/lib/naive/strategy.ex index 77e639d..d9ecbab 100644 --- a/apps/naive/lib/naive/strategy.ex +++ b/apps/naive/lib/naive/strategy.ex @@ -3,14 +3,12 @@ defmodule Naive.Strategy do Module in charge of making and executing decisions """ alias Core.Struct.TradeEvent + alias Naive.Repo alias Naive.Schema.Settings require Logger @binance_client Application.compile_env(:naive, :binance_client) - @logger Application.compile_env(:core, :logger) - @pubsub_client Application.compile_env(:core, :pubsub_client) - @repo Application.compile_env(:naive, :repo) defmodule Position do @enforce_keys [ @@ -255,7 +253,7 @@ defmodule Naive.Strategy do } = position, _settings ) do - @logger.info( + Logger.info( "Position (#{symbol}/#{id}): " <> "Placing a BUY order @ #{price}, quantity: #{quantity}" ) @@ -279,7 +277,7 @@ defmodule Naive.Strategy do } = position, _settings ) do - @logger.info( + Logger.info( "Position (#{symbol}/#{id}): The BUY order is now filled. " <> "Placing a SELL order @ #{sell_price}, quantity: #{quantity}" ) @@ -305,7 +303,7 @@ defmodule Naive.Strategy do } = position, _settings ) do - @logger.info("Position (#{symbol}/#{id}): The BUY order is now partially filled") + Logger.info("Position (#{symbol}/#{id}): The BUY order is now partially filled") {:ok, %Binance.Order{} = current_buy_order} = @binance_client.get_order(symbol, timestamp, order_id) @@ -324,7 +322,7 @@ defmodule Naive.Strategy do settings ) do new_position = generate_fresh_position(settings) - @logger.info("Position (#{symbol}/#{id}): Trade cycle finished") + Logger.info("Position (#{symbol}/#{id}): Trade cycle finished") {:ok, new_position} end @@ -341,7 +339,7 @@ defmodule Naive.Strategy do } = position, _settings ) do - @logger.info("Position (#{symbol}/#{id}): The SELL order is now partially filled") + Logger.info("Position (#{symbol}/#{id}): The SELL order is now partially filled") {:ok, %Binance.Order{} = current_sell_order} = @binance_client.get_order(symbol, timestamp, order_id) @@ -360,7 +358,7 @@ defmodule Naive.Strategy do settings ) do new_position = generate_fresh_position(settings) - @logger.info("Position (#{symbol}/#{id}): Rebuy triggered. Starting a new position") + Logger.info("Position (#{symbol}/#{id}): Rebuy triggered. Starting a new position") {:ok, new_position} end @@ -375,7 +373,7 @@ defmodule Naive.Strategy do end defp broadcast_order(%Binance.Order{} = order) do - @pubsub_client.broadcast(Core.PubSub, "ORDERS:#{order.symbol}", order) + Phoenix.PubSub.broadcast(Core.PubSub, "ORDERS:#{order.symbol}", order) end defp convert_to_order(%Binance.OrderResponse{} = response) do @@ -395,7 +393,7 @@ defmodule Naive.Strategy do exchange_info = @binance_client.get_exchange_info() - db_settings = @repo.get_by!(Settings, symbol: symbol) + db_settings = Repo.get_by!(Settings, symbol: symbol) merge_filters_into_settings(exchange_info, db_settings, symbol) end @@ -437,8 +435,8 @@ defmodule Naive.Strategy do end def update_status(symbol, status) when is_binary(symbol) and is_binary(status) do - @repo.get_by(Settings, symbol: symbol) + Repo.get_by(Settings, symbol: symbol) |> Ecto.Changeset.change(%{status: status}) - |> @repo.update() + |> Repo.update() end end diff --git a/apps/naive/lib/naive/trader.ex b/apps/naive/lib/naive/trader.ex index 7e220ad..d759dbb 100644 --- a/apps/naive/lib/naive/trader.ex +++ b/apps/naive/lib/naive/trader.ex @@ -10,8 +10,6 @@ defmodule Naive.Trader do require Logger - @logger Application.compile_env(:core, :logger) - @pubsub_client Application.compile_env(:core, :pubsub_client) @registry :naive_traders defmodule State do @moduledoc """ @@ -27,9 +25,9 @@ defmodule Naive.Trader do end def init(symbol) do - @logger.info("Initializing new trader for #{symbol}") + Logger.info("Initializing new trader for #{symbol}") - @pubsub_client.subscribe(Core.PubSub, "TRADE_EVENTS:#{symbol}") + Phoenix.PubSub.subscribe(Core.PubSub, "TRADE_EVENTS:#{symbol}") {:ok, nil, {:continue, {:start_position, symbol}}} end diff --git a/apps/naive/mix.exs b/apps/naive/mix.exs index c479a45..75b233c 100644 --- a/apps/naive/mix.exs +++ b/apps/naive/mix.exs @@ -15,8 +15,7 @@ defmodule Naive.MixProject do elixirc_options: [ warnings_as_errors: true ], - aliases: aliases(), - elixirc_paths: elixirc_paths(Mix.env()) + aliases: aliases() ] end @@ -44,13 +43,10 @@ defmodule Naive.MixProject do {:decimal, "~> 2.0"}, {:ecto_sql, "~> 3.0"}, {:ecto_enum, "~> 1.4"}, + {:mimic, "~> 1.7", only: [:test, :integration]}, {:phoenix_pubsub, "~> 2.0"}, {:postgrex, ">= 0.0.0"}, - {:sobelow, "~> 0.13", only: [:dev, :test], runtime: false}, - {:mox, "~> 1.0", only: [:test, :integration]} + {:sobelow, "~> 0.13", only: [:dev, :test], runtime: false} ] end - - defp elixirc_paths(:test), do: ["test/support", "lib"] - defp elixirc_paths(_), do: ["lib"] end diff --git a/apps/naive/test/naive/strategy_test.exs b/apps/naive/test/naive/strategy_test.exs new file mode 100644 index 0000000..963e80c --- /dev/null +++ b/apps/naive/test/naive/strategy_test.exs @@ -0,0 +1,66 @@ +defmodule Naive.StrategyTest do + use ExUnit.Case, async: true + use Mimic + + alias Core.Struct.TradeEvent + alias Naive.Strategy + import ExUnit.CaptureLog + + @tag :unit + test "Strategy places a buy order" do + expected_order = %Binance.OrderResponse{ + client_order_id: "1", + executed_qty: "0.000", + order_id: "x1", + orig_qty: "50.000", + price: "0.800000", + side: "BUY", + status: "NEW", + symbol: "ABC" + } + + BinanceMock + |> stub( + :order_limit_buy, + fn "ABC", "50.000", "0.800000", "GTC" -> {:ok, expected_order} end + ) + + Phoenix.PubSub + |> stub( + :broadcast, + fn _pubsub, _topic, _message -> :ok end + ) + + settings = %{ + symbol: "ABC", + chunks: "5", + budget: "200", + buy_down_interval: "0.2", + profit_interval: "0.1", + rebuy_interval: "0.5", + tick_size: "0.000001", + step_size: "0.001", + status: :on + } + + {{:ok, new_positions}, log} = + with_log(fn -> + Naive.Strategy.execute( + %TradeEvent{ + price: "1.00000" + }, + [ + Strategy.generate_fresh_position(settings) + ], + settings + ) + end) + + assert log =~ "0.8" + + assert length(new_positions) == 1 + + %{buy_order: buy_order} = List.first(new_positions) + assert buy_order == expected_order + end +end diff --git a/apps/naive/test/naive/trader_test.exs b/apps/naive/test/naive/trader_test.exs index 457f970..565815e 100644 --- a/apps/naive/test/naive/trader_test.exs +++ b/apps/naive/test/naive/trader_test.exs @@ -1,73 +1,73 @@ -defmodule Naive.TraderTest do - use ExUnit.Case - doctest Naive.Trader +# defmodule Naive.TraderTest do +# use ExUnit.Case +# doctest Naive.Trader - import Mox +# import Mox - setup :set_mox_from_context - setup :verify_on_exit! +# setup :set_mox_from_context +# setup :verify_on_exit! - @tag :unit - test "Placing buy order test" do - Test.PubSubMock - |> expect(:subscribe, fn _module, "TRADE_EVENTS:XRPUSDT" -> :ok end) - |> expect(:broadcast, fn _module, "ORDERS:XRPUSDT", _order -> :ok end) +# @tag :unit +# test "Placing buy order test" do +# Test.PubSubMock +# |> expect(:subscribe, fn _module, "TRADE_EVENTS:XRPUSDT" -> :ok end) +# |> expect(:broadcast, fn _module, "ORDERS:XRPUSDT", _order -> :ok end) - Test.BinanceMock - |> expect(:order_limit_buy, fn "XRPUSDT", "464.360", "0.4307", "GTC" -> - {:ok, - BinanceMock.generate_fake_order("12345", "XRPUSDT", "464.360", "0.4307", "BUY") - |> BinanceMock.convert_order_to_order_response()} - end) +# Test.BinanceMock +# |> expect(:order_limit_buy, fn "XRPUSDT", "464.360", "0.4307", "GTC" -> +# {:ok, +# BinanceMock.generate_fake_order("12345", "XRPUSDT", "464.360", "0.4307", "BUY") +# |> BinanceMock.convert_order_to_order_response()} +# end) - test_pid = self() +# test_pid = self() - Test.Naive.LeaderMock - |> expect(:notify, fn :trader_state_updated, %Naive.Trader.State{} -> - send(test_pid, :ok) - :ok - end) +# Test.Naive.LeaderMock +# |> expect(:notify, fn :trader_state_updated, %Naive.Trader.State{} -> +# send(test_pid, :ok) +# :ok +# end) - Test.LoggerMock - |> expect(:info, 2, fn _message -> :ok end) +# Test.LoggerMock +# |> expect(:info, 2, fn _message -> :ok end) - trader_state = dummy_trader_state() +# trader_state = dummy_trader_state() - trade_event = generate_event(1, "0.43183010", "213.10000000") +# trade_event = generate_event(1, "0.43183010", "213.10000000") - {:ok, trader_pid} = Naive.Trader.start_link(trader_state) - send(trader_pid, trade_event) - assert_receive :ok - end +# {:ok, trader_pid} = Naive.Trader.start_link(trader_state) +# send(trader_pid, trade_event) +# assert_receive :ok +# end - defp dummy_trader_state() do - %Naive.Strategy.Position{ - id: 100_000_000, - symbol: "XRPUSDT", - budget: "200", - buy_order: nil, - sell_order: nil, - buy_down_interval: Decimal.new("0.0025"), - profit_interval: Decimal.new("0.001"), - rebuy_interval: Decimal.new("0.006"), - rebuy_notified: false, - tick_size: "0.0001", - step_size: "0.001" - } - end +# defp dummy_trader_state() do +# %Naive.Strategy.Position{ +# id: 100_000_000, +# symbol: "XRPUSDT", +# budget: "200", +# buy_order: nil, +# sell_order: nil, +# buy_down_interval: Decimal.new("0.0025"), +# profit_interval: Decimal.new("0.001"), +# rebuy_interval: Decimal.new("0.006"), +# rebuy_notified: false, +# tick_size: "0.0001", +# step_size: "0.001" +# } +# end - defp generate_event(id, price, quantity) do - %Core.Struct.TradeEvent{ - event_type: "trade", - event_time: 1_000 + id * 10, - symbol: "XRPUSDT", - trade_id: 2_000 + id * 10, - price: price, - quantity: quantity, - buyer_order_id: 3_000 + id * 10, - seller_order_id: 4_000 + id * 10, - trade_time: 5_000 + id * 10, - buyer_market_maker: false - } - end -end +# defp generate_event(id, price, quantity) do +# %Core.Struct.TradeEvent{ +# event_type: "trade", +# event_time: 1_000 + id * 10, +# symbol: "XRPUSDT", +# trade_id: 2_000 + id * 10, +# price: price, +# quantity: quantity, +# buyer_order_id: 3_000 + id * 10, +# seller_order_id: 4_000 + id * 10, +# trade_time: 5_000 + id * 10, +# buyer_market_maker: false +# } +# end +# end diff --git a/apps/naive/test/test_helper.exs b/apps/naive/test/test_helper.exs index 6a7d16c..1643e07 100644 --- a/apps/naive/test/test_helper.exs +++ b/apps/naive/test/test_helper.exs @@ -1,9 +1,6 @@ -ExUnit.start() +Application.ensure_all_started(:mimic) -Application.ensure_all_started(:mox) -# here I differed a little bit from the book cause in has -# warning_as_errors turned on and i needed compile time checks -# Mox.defmock(Test.BinanceMock, for: BinanceMock) -# Mox.defmock(Test.Naive.LeaderMock, for: Naive.Leader) -# Mox.defmock(Test.LoggerMock, for: Core.Test.Logger) -# Mox.defmock(Test.PubSubMock, for: Core.Test.PubSub) +Mimic.copy(BinanceMock) +Mimic.copy(Phoenix.PubSub) + +ExUnit.start(capture_log: true) diff --git a/config/config.exs b/config/config.exs index f17d5ba..b239a06 100644 --- a/config/config.exs +++ b/config/config.exs @@ -3,10 +3,6 @@ import Config config :binance_mock, use_cached_exchange_info: false -config :core, - logger: Logger, - pubsub_client: Phoenix.PubSub - config :data_warehouse, ecto_repos: [DataWarehouse.Repo] @@ -29,8 +25,6 @@ config :streamer, Streamer.Repo, config :naive, binance_client: BinanceMock, ecto_repos: [Naive.Repo], - leader: Naive.Leader, - repo: Naive.Repo, trading: %{ defaults: %{ chunks: 5, diff --git a/config/test.exs b/config/test.exs index 475191f..becde76 100644 --- a/config/test.exs +++ b/config/test.exs @@ -1,10 +1 @@ import Config - -config :core, - logger: Test.LoggerMock, - pubsub_client: Test.PubSubMock - -config :naive, - binance_client: Test.BinanceMock, - leader: Test.Naive.LeaderMock, - repo: Test.Naive.RepoMock diff --git a/mix.lock b/mix.lock index 9fafd58..c0c5821 100644 --- a/mix.lock +++ b/mix.lock @@ -11,11 +11,13 @@ "exconstructor": {:hex, :exconstructor, "1.2.10", "72a540c89b4c5af75f88c076727c0318a8f4038df6412dcf546e8771dcac118d", [:mix], [], "hexpm", "6e504f88cc56c3a7313f0d7687c5d3454b014255867232957512a61e5f90bea7"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, + "ham": {:hex, :ham, "0.3.0", "7cd031b4a55fba219c11553e7b13ba73bd86eab4034518445eff1e038cb9a44d", [:mix], [], "hexpm", "7d6c6b73d7a6a83233876cc1b06a4d9b5de05562b228effda4532f9a49852bf6"}, "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, + "mimic": {:hex, :mimic, "1.11.1", "08b8f82d760ae19bdca698a2c0714921ba41c854959ff58faebb3021f914f9a7", [:mix], [{:ham, "~> 0.2", [hex: :ham, repo: "hexpm", optional: false]}], "hexpm", "bcb35db46dbf089dd026f3a7a8b772c2220124492eeae0533ac5719c505dec53"}, "mox": {:hex, :mox, "1.1.0", "0f5e399649ce9ab7602f72e718305c0f9cdc351190f72844599545e4996af73c", [:mix], [], "hexpm", "d44474c50be02d5b72131070281a5d3895c0e7a95c780e90bc0cfe712f633a13"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, diff --git a/notes/notes.md b/notes/notes.md index 18a0004..b9c638a 100644 --- a/notes/notes.md +++ b/notes/notes.md @@ -160,3 +160,19 @@ build, convert or transforms, CRC -> construct reduce convert is better to not overoptimize, sometime a simple proccess with a tasks can handle the load, do not optimize ahead of time + +## Chapter 21 +when integrating with third party libraries using an "e-z replaceable" module is desired, something like +creating an api inside the code +I really believe this chapter could introduce a "real" migration instead of replacing old fields. + +I like the idea to base yourself in already existing implementations instead of over-engineer and try to come up with everything from scratch + + +this chapter is was really hard to follow along cause what was in the book +was not the same that was the same that is reflected in the branches, first example `apps/data_warehouse/lib/data_warehouse/schema/order.ex` + +it results that i need to revert to chapter 20 an remove all the mox shenanigans +cause it was really slow me down for a while, but it really taugh me that abandon things and revisiting them later with a fresh head could bring beneficts + + From f42c3f950366a1a72c9d56bad5ae75e2d149844e Mon Sep 17 00:00:00 2001 From: Bodhert Date: Sat, 17 May 2025 20:40:32 -0500 Subject: [PATCH 2/2] sync with franton code --- apps/indicator/lib/indicator/ohlc/worker.ex | 2 +- apps/naive/test/naive/trader_test.exs | 73 --------------------- 2 files changed, 1 insertion(+), 74 deletions(-) delete mode 100644 apps/naive/test/naive/trader_test.exs diff --git a/apps/indicator/lib/indicator/ohlc/worker.ex b/apps/indicator/lib/indicator/ohlc/worker.ex index 881ef6e..9117a2d 100644 --- a/apps/indicator/lib/indicator/ohlc/worker.ex +++ b/apps/indicator/lib/indicator/ohlc/worker.ex @@ -9,7 +9,7 @@ defmodule Indicator.Ohlc.Worker do def init(symbol) do symbol = String.upcase(symbol) - Logger.debug("Initializing a new OHLC worker for #{symbol}") + Logger.info("Initializing a new OHLC worker for #{symbol}") Phoenix.PubSub.subscribe( Core.PubSub, diff --git a/apps/naive/test/naive/trader_test.exs b/apps/naive/test/naive/trader_test.exs deleted file mode 100644 index 565815e..0000000 --- a/apps/naive/test/naive/trader_test.exs +++ /dev/null @@ -1,73 +0,0 @@ -# defmodule Naive.TraderTest do -# use ExUnit.Case -# doctest Naive.Trader - -# import Mox - -# setup :set_mox_from_context -# setup :verify_on_exit! - -# @tag :unit -# test "Placing buy order test" do -# Test.PubSubMock -# |> expect(:subscribe, fn _module, "TRADE_EVENTS:XRPUSDT" -> :ok end) -# |> expect(:broadcast, fn _module, "ORDERS:XRPUSDT", _order -> :ok end) - -# Test.BinanceMock -# |> expect(:order_limit_buy, fn "XRPUSDT", "464.360", "0.4307", "GTC" -> -# {:ok, -# BinanceMock.generate_fake_order("12345", "XRPUSDT", "464.360", "0.4307", "BUY") -# |> BinanceMock.convert_order_to_order_response()} -# end) - -# test_pid = self() - -# Test.Naive.LeaderMock -# |> expect(:notify, fn :trader_state_updated, %Naive.Trader.State{} -> -# send(test_pid, :ok) -# :ok -# end) - -# Test.LoggerMock -# |> expect(:info, 2, fn _message -> :ok end) - -# trader_state = dummy_trader_state() - -# trade_event = generate_event(1, "0.43183010", "213.10000000") - -# {:ok, trader_pid} = Naive.Trader.start_link(trader_state) -# send(trader_pid, trade_event) -# assert_receive :ok -# end - -# defp dummy_trader_state() do -# %Naive.Strategy.Position{ -# id: 100_000_000, -# symbol: "XRPUSDT", -# budget: "200", -# buy_order: nil, -# sell_order: nil, -# buy_down_interval: Decimal.new("0.0025"), -# profit_interval: Decimal.new("0.001"), -# rebuy_interval: Decimal.new("0.006"), -# rebuy_notified: false, -# tick_size: "0.0001", -# step_size: "0.001" -# } -# end - -# defp generate_event(id, price, quantity) do -# %Core.Struct.TradeEvent{ -# event_type: "trade", -# event_time: 1_000 + id * 10, -# symbol: "XRPUSDT", -# trade_id: 2_000 + id * 10, -# price: price, -# quantity: quantity, -# buyer_order_id: 3_000 + id * 10, -# seller_order_id: 4_000 + id * 10, -# trade_time: 5_000 + id * 10, -# buyer_market_maker: false -# } -# end -# end