Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial pass at Synth-based ticker selection #1392

Merged
merged 15 commits into from
Oct 30, 2024
Merged

Initial pass at Synth-based ticker selection #1392

merged 15 commits into from
Oct 30, 2024

Conversation

Shpigford
Copy link
Member

No description provided.

@Shpigford
Copy link
Member Author

Shpigford commented Oct 29, 2024

@josefarias Sorry to keep pinging you about this but alas...

CleanShot.2024-10-29.at.19.08.38.mp4

Selecting the item from the dropdown is filling in the input with the full hash. Not sure how to address that.

What I'm ultimately trying to do is have the fancy dropdown and then have the value on selection be something like AAPL (NYSE) (ticker + mic code).

I'm almost certainly doing something very wrong here...I just don't know what...

<%= async_combobox_options @securities.map { |security| 
      { 
        display: security,
        value: security[:symbol]
      }
    },
    render_in: { partial: "account/trades/tickers" } %>

@securities is an array of hashes...

[{:symbol=>"AAPL", :name=>"Apple Inc.", :logo_url=>"https://logo.synthfinance.com/ticker/AAPL", :exchange_acronym=>"NASDAQ"}, {:symbol=>"AAPL", :name=>"Apple Inc", :logo_url=>"https://logo.synthfinance.com/ticker/AAPL", :exchange_acronym=>"NASDAQ"}, {:symbol=>"AAPD", :name=>"Direxion Daily AAPL Bear 1X Shares", :logo_url=>"https://logo.synthfinance.com/ticker/AAPD", :exchange_acronym=>"NASDAQ"}, {:symbol=>"AAPY", :name=>"Kurv Yield Premium Strategy Apple (AAPL) ETF", :logo_url=>"https://logo.synthfinance.com/ticker/AAPY", :exchange_acronym=>"CBOE"}, {:symbol=>"APLY", :name=>"YieldMax AAPL Option Income Strategy ETF", :logo_url=>"https://logo.synthfinance.com/ticker/APLY", :exchange_acronym=>"NYSE"}, {:symbol=>"AAPU", :name=>"Direxion Shares ETF Trust Direxion Daily AAPL Bull 2X Shares", :logo_url=>"https://logo.synthfinance.com/ticker/AAPU", :exchange_acronym=>"NASDAQ"}, {:symbol=>"AAPB", :name=>"GraniteShares ETF Trust GraniteShares 2x Long AAPL Daily ETF", :logo_url=>"https://logo.synthfinance.com/ticker/AAPB", :exchange_acronym=>"NASDAQ"}]

@Shpigford
Copy link
Member Author

@zachgoll If you could review how I'm using the Providable stuff, that'd be great. It seems to work, but just not positive I'm using it as intended.

@Shpigford
Copy link
Member Author

Current status: combobox seems functional, however on form submission the "ticker" field is submitting "undefined".

Parameters: {"authenticity_token"=>"[FILTERED]", "account_entry"=>{"type"=>"buy", "ticker"=>"undefined", "date"=>"2024-10-16", "amount"=>"", "transfer_account_id"=>"", "qty"=>"25", "price"=>"100"}, "commit"=>"Add transaction", "account_id"=>"4ab6e059-8bca-490a-9958-8e3fc96346f4"}

@josefarias
Copy link
Contributor

@Shpigford ah, the state of the PR changed after I checked out the code. But the same ideas apply.

This is pretty custom usage, where you essentially have two displays — one for each option in the listbox (HTML) and another to display in the input when an option is selected ("#{symbol} - #{name} (#{exchange_acronym})"). This is possible with HotwireCombobox but it'll require passing in an array of objects. This is working for me locally:

diff --git a/app/controllers/account/trades_controller.rb b/app/controllers/account/trades_controller.rb
index 8d31d3a..ea70af0 100644
--- a/app/controllers/account/trades_controller.rb
+++ b/app/controllers/account/trades_controller.rb
@@ -36,9 +36,7 @@ class Account::TradesController < ApplicationController
   def securities
     query = params[:q]
     return render json: [] if query.blank? || query.length < 2 || query.length > 100
-
-    synth_client = Provider::Synth.new(ENV["SYNTH_API_KEY"])
-    @securities = synth_client.search_securities(query:, dataset: "limited", country_code: Current.family.country).securities
+    @securities = Security::SynthComboboxOption.find_in_synth(query)
   end
 
   private
diff --git a/app/models/security/synth_combobox_option.rb b/app/models/security/synth_combobox_option.rb
new file mode 100644
index 0000000..fe1fe07
--- /dev/null
+++ b/app/models/security/synth_combobox_option.rb
@@ -0,0 +1,22 @@
+class Security::SynthComboboxOption
+  include ActiveModel::Model
+
+  attr_accessor :symbol, :name, :logo_url, :exchange_acronym
+
+  class << self
+    def find_in_synth(query)
+      Provider::Synth.new(ENV["SYNTH_API_KEY"])
+        .search_securities(query:, dataset: "limited", country_code: Current.family.country)
+        .securities
+        .map { |attrs| new(**attrs) }
+    end
+  end
+
+  def id
+    symbol # submitted by combobox as value
+  end
+
+  def to_combobox_display
+    "#{symbol} - #{name} (#{exchange_acronym})" # shown in combobox input when selected
+  end
+end
diff --git a/app/views/account/trades/_tickers.turbo_stream.erb b/app/views/account/trades/_tickers.turbo_stream.erb
index 20bf8f9..9dba791 100644
--- a/app/views/account/trades/_tickers.turbo_stream.erb
+++ b/app/views/account/trades/_tickers.turbo_stream.erb
@@ -1,11 +1,11 @@
 <div class="flex items-center">
-  <%= image_tag(tickers[:logo_url], class: "rounded-full h-8 w-8 inline-block mr-2" ) %>
+  <%= image_tag(tickers.logo_url, class: "rounded-full h-8 w-8 inline-block mr-2" ) %>
     <div class="flex flex-col">
       <span class="text-sm font-medium">
-        <%= tickers[:name].presence || tickers[:symbol] %>
+        <%= tickers.name.presence || tickers.symbol %>
       </span>
       <span class="text-xs text-gray-500">
-        <%= "#{tickers[:symbol]} (#{tickers[:exchange_acronym]})" %>
+        <%= "#{tickers.symbol} (#{tickers.exchange_acronym})" %>
       </span>
     </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/app/views/account/trades/securities.turbo_stream.erb b/app/views/account/trades/securities.turbo_stream.erb
index f7fcaf2..4e4b1af 100644
--- a/app/views/account/trades/securities.turbo_stream.erb
+++ b/app/views/account/trades/securities.turbo_stream.erb
@@ -1,7 +1 @@
-<%= async_combobox_options @securities.map { |security| 
-      { 
-        display: security,
-        value: security[:symbol]
-      }
-    },
-    render_in: { partial: "account/trades/tickers" } %>
\ No newline at end of file
+<%= async_combobox_options @securities, render_in: { partial: "account/trades/tickers" } %>

@josefarias
Copy link
Contributor

josefarias commented Oct 30, 2024

Additionally, I'd suggest renaming app/views/account/trades/_tickers.turbo_stream.erb to app/views/account/trades/_ticker.turbo_stream.erb to avoid further confusion, since the partial is rendered once for each ticker. If you do rename, you'll have to change all the references in the partial from tickers to ticker.

@Shpigford
Copy link
Member Author

@josefarias Looks like @zachgoll's changes were on the right track (they're pushed to the PR now).

@Shpigford
Copy link
Member Author

@josefarias Just merged yours and @zachgoll's solutions and it works beautifully. 🙂 Thanks a ton!

@Shpigford Shpigford marked this pull request as ready for review October 30, 2024 12:17
@Shpigford Shpigford merged commit cd91e66 into main Oct 30, 2024
5 checks passed
@Shpigford Shpigford deleted the synth-selector branch October 30, 2024 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants