Cinderella-Man / hands-on-elixir-and-otp-cryptocurrency-trading-bot-source-code

Resources related to the "Hands-on Elixir & OTP: Cryptocurrency trading bot" book
https://elixircryptobot.com
76 stars 25 forks source link

Chapter 02 - error: Streamer.Binance.OrderResponse.__struct__/0 is undefined, #24

Closed sebastianbachmann closed 1 year ago

sebastianbachmann commented 1 year ago

Hello,

i am currently working through the book and i am stuck within chapter 02 Create a naive traing strategy on page 27.

# /apps/naive/lib/naive/trader.ex
def handle_cast(
      %TradeEvent{price: price},
      %State{symbol: symbol, buy_order: nil} = state
    ) do

  quantity = "100" # <= Hardcoded until chapter 7
  Logger.info("Placing BUY order for #{symbol} @ #{price}, quantity: #{quantity}")

  {:ok, %Binance.OrderResponse{} = order} =
    Binance.order_limit_buy(symbol, quantity, price, "GTC")

  {:noreply, %{state | buy_order: order}}
end

When i am running iex -S mix the compiler is complaining about

Compiling 3 files (.ex)
error: Streamer.Binance.OrderResponse.__struct__/0 is undefined, cannot expand struct Streamer.Binance.OrderResponse. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code
  lib/naive/trader.ex:47: Naive.Trader.handle_cast/2

== Compilation error in file lib/naive/trader.ex ==
** (CompileError) lib/naive/trader.ex: cannot compile module Naive.Trader (errors have been logged)

I looked into the Binance folder within deps/binance/lib/binance/structs/order_response.ex and found the OrderResponse struct, so i am not really sure what i am missing.

Appreciate your help, thanks!

Cinderella-Man commented 1 year ago

Hey :wave:

Thanks for posting this issue. After a brief look I think your codebase is pointing to a wrong module name(Streamer.Binance.OrderResponse based on error). The Streamer application doesn't have the Streamer.Binance.OrderResponse struct - that struct it's part of the Binance package/module - could you please double check your aliases as I believe that you are probably doing something like:

alias Streamer.Binance

which now will collide with the Binance module from the Binance package. That's my best guess - Elixir gets confused then when you refer to Binance.OrderResponse thinking that it needs to expand the module name(based on the alias alias Streamer.Binance that doesn't appear in the book/codebase to avoid this issue) to Streamer.Binance.OrderResponse instead of looking at the Binance module.

Please let me know was this correct assumption and clear explanation

sebastianbachmann commented 1 year ago

Hey 👋

i've had some aliases defined - somehow this happens automagically 🤔 - but removed them and ended up with those two

alias Streamer.Binance.TradeEvent
alias Decimal, as: D

as pointed out in the book. But the error message still exists. I've pushed the source code with my current state, and if you don't mind please have a look, if you have some time. Thanks!

https://github.com/sebastianbachmann/crypto-trading-bot/commit/d11e5a579eeb81feb816fc21de965a8cd7bd8d8f

I am using the following versions of Elixir and OTP

Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]

Elixir 1.15.4 (compiled with Erlang/OTP 26)
Cinderella-Man commented 1 year ago

Hello again :wave:

Thanks for more info and pushing the code, So after reviewing the changes I realised that you are using version 2(or newer) of the binance module:

https://github.com/sebastianbachmann/crypto-trading-bot/commit/d11e5a579eeb81feb816fc21de965a8cd7bd8d8f#diff-605a68cb0c3faa6957a1bc843bb269beb469fb9318afeb5a311a936358fbcda3R29

The book is using version 1.x:

https://github.com/Cinderella-Man/hands-on-elixir-and-otp-cryptocurrency-trading-bot-source-code/blob/chapter_02/apps/naive/mix.exs#L29

Version two was released recently and I didn't update the book to work with it (yet :thinking:). After quick comparison of the source code I can see that the version 1.x contains the Binance.OrderResponse module:

https://github.com/dvcrn/binance.ex/blob/v1/lib/binance/order_response.ex#L1

Where the version 2.0 moved it to Binance.Structs.OrderResponse:

https://github.com/dvcrn/binance.ex/blob/master/lib/binance/structs/order_response.ex#L1

Both structs appear to look exactly the same so probably you could update all references through rest of the book to contain .Structs submodule when referring to data returned from Binance module. Otherwise, most likely it would be easier to downgrade the binance module version to 1.x in your mix.exs file.

Please let me know have I got it right this time :slightly_smiling_face:

sebastianbachmann commented 1 year ago

Hello 👋

Yikes, this was totally my fault, sorry 😏

I've downgraded to 1.x because updating the references to contain the submodule .Structs would lead to another error within e.g. the Tuple .order_limit_buy()

    {:ok, %Binance.OrderResponse{} = order} =
      Binance.order_limit_buy(symbol, quantity, price, ~c"GTC") # there was an error raised i could not solve

Thanks, i appreciate your help 🙂✌️

Cinderella-Man commented 1 year ago

No need to be sorry - happens to best of us! :slightly_smiling_face:

Thank you for taking time to read my book and best of luck on your Elixir journey :rocket: