Skip to content

Commit

Permalink
Remove dependency on stock exchange table (maybe-finance#1368)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shpigford authored Oct 25, 2024
1 parent b75b41a commit 45935db
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 22 deletions.
3 changes: 2 additions & 1 deletion app/models/provider/marketstack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ def fetch_tickers(exchange_mic: nil)
{
name: ticker["name"],
symbol: ticker["symbol"],
exchange: exchange_mic || ticker.dig("stock_exchange", "mic"),
exchange_mic: exchange_mic || ticker.dig("stock_exchange", "mic"),
exchange_acronym: ticker.dig("stock_exchange", "acronym"),
country_code: ticker.dig("stock_exchange", "country_code")
}
end
Expand Down
3 changes: 2 additions & 1 deletion app/models/security.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ class Security < ApplicationRecord

has_many :trades, dependent: :nullify, class_name: "Account::Trade"

validates :ticker, presence: true, uniqueness: { case_sensitive: false }
validates :ticker, presence: true
validates :ticker, uniqueness: { scope: :exchange_mic, case_sensitive: false }

def current_price
@current_price ||= Security::Price.find_price(ticker:, date: Date.current)
Expand Down
33 changes: 18 additions & 15 deletions app/models/security/importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@ def initialize(provider, stock_exchange = nil)
def import
securities = @provider.fetch_tickers(exchange_mic: @stock_exchange)&.tickers

stock_exchanges = StockExchange.where(mic: securities.map { |s| s[:exchange] }).index_by(&:mic)
existing_securities = Security.where(ticker: securities.map { |s| s[:symbol] }, stock_exchange_id: stock_exchanges.values.map(&:id)).pluck(:ticker, :stock_exchange_id).to_set
# Deduplicate securities based on ticker and exchange_mic
securities_to_create = securities
.map do |security|
{
name: security[:name],
ticker: security[:symbol],
country_code: security[:country_code],
exchange_mic: security[:exchange_mic],
exchange_acronym: security[:exchange_acronym]
}
end
.compact
.uniq { |security| [ security[:ticker], security[:exchange_mic] ] }

securities_to_create = securities.map do |security|
stock_exchange_id = stock_exchanges[security[:exchange]]&.id
next if existing_securities.include?([ security[:symbol], stock_exchange_id ])

{
name: security[:name],
ticker: security[:symbol],
stock_exchange_id: stock_exchange_id,
country_code: security[:country_code]
}
end.compact

Security.insert_all(securities_to_create) unless securities_to_create.empty?
Security.upsert_all(
securities_to_create,
unique_by: [ :ticker, :exchange_mic ],
update_only: [ :name, :country_code, :exchange_acronym ]
) unless securities_to_create.empty?
end
end
2 changes: 1 addition & 1 deletion config/initializers/good_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# Auth for jobs admin dashboard
ActiveSupport.on_load(:good_job_application_controller) do
before_action do
raise ActionController::RoutingError.new("Not Found") unless current_user&.super_admin?
raise ActionController::RoutingError.new("Not Found") unless current_user&.super_admin? || Rails.env.development?
end

def current_user
Expand Down
10 changes: 10 additions & 0 deletions db/migrate/20241025174650_add_mic_to_securities.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class AddMicToSecurities < ActiveRecord::Migration[7.2]
def change
add_column :securities, :exchange_mic, :string
add_column :securities, :exchange_acronym, :string

remove_column :securities, :stock_exchange_id, :uuid

add_index :securities, [ :ticker, :exchange_mic ], unique: true
end
end
8 changes: 4 additions & 4 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 45935db

Please sign in to comment.