-
Notifications
You must be signed in to change notification settings - Fork 0
feat: adds series event lookup, and events/ endpoints #13
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
Changes from all commits
c777626
cf1a728
0239da3
d895a9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Rubyists | ||
| module Kalshi | ||
| module Events | ||
| # Events API Client | ||
| class Client < ApiClient | ||
| def list(...) | ||
| List.new(client).list(...) | ||
| end | ||
|
|
||
| def fetch(...) | ||
| List.new(client).fetch(...) | ||
| end | ||
|
|
||
| def metadata(...) | ||
| List.new(client).metadata(...) | ||
| end | ||
|
|
||
| def multivariate | ||
| Multivariate.new(client) | ||
| end | ||
|
|
||
| def candlesticks | ||
| Rubyists::Kalshi::Series::EventCandlesticks.new(client) | ||
|
Comment on lines
+24
to
+25
|
||
| end | ||
| end | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Rubyists | ||
| module Kalshi | ||
| module Events | ||
| # Events API endpoint | ||
| class List < Kalshi::Endpoint | ||
| include Kalshi::Listable | ||
|
|
||
| kalshi_path '' | ||
|
|
||
| # Filter for Kalshi events list | ||
| class Filter < Kalshi::Contract | ||
| propertize(%i[limit cursor status series_ticker with_nested_markets]) | ||
|
|
||
| validation do | ||
| params do | ||
| optional(:limit).maybe(:integer) | ||
| optional(:cursor).maybe(:string) | ||
| optional(:status).maybe(:string) | ||
| optional(:series_ticker).maybe(:string) | ||
| optional(:with_nested_markets).maybe(:bool) | ||
| end | ||
| end | ||
| end | ||
|
|
||
| def fetch(event_ticker) | ||
| client.get(event_ticker) | ||
| end | ||
|
|
||
| def metadata(event_ticker) | ||
| client.get("#{event_ticker}/metadata") | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Rubyists | ||
| module Kalshi | ||
| module Events | ||
| # Multivariate Events API endpoint | ||
| class Multivariate < Kalshi::Endpoint | ||
| include Kalshi::Listable | ||
|
|
||
| kalshi_path 'multivariate' | ||
|
|
||
| # Filter for Kalshi multivariate events list | ||
| class Filter < Kalshi::Contract | ||
| propertize(%i[limit cursor series_ticker collection_ticker]) | ||
|
|
||
| validation do | ||
| params do | ||
| optional(:limit).maybe(:integer) | ||
| optional(:cursor).maybe(:string) | ||
| optional(:series_ticker).maybe(:string) | ||
| optional(:collection_ticker).maybe(:string) | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Rubyists | ||
| module Kalshi | ||
| module Series | ||
| # Series API Client | ||
| class Client < ApiClient | ||
| def event_candlesticks | ||
| EventCandlesticks.new(client) | ||
| end | ||
|
|
||
| def forecast_percentile_history | ||
| ForecastPercentileHistory.new(client) | ||
| end | ||
|
Comment on lines
+8
to
+14
|
||
| end | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,34 @@ | ||||||
| # frozen_string_literal: true | ||||||
|
|
||||||
| module Rubyists | ||||||
| module Kalshi | ||||||
| module Series | ||||||
| # Event Candlesticks API endpoint | ||||||
| class EventCandlesticks < Kalshi::Endpoint | ||||||
| # Filter for Event Candlesticks | ||||||
| class EventFilter < Kalshi::Contract | ||||||
| propertize(%i[series_ticker ticker start_ts end_ts period_interval]) | ||||||
|
|
||||||
| validation do | ||||||
| params do | ||||||
| required(:series_ticker).filled(:string) | ||||||
| required(:ticker).filled(:string) | ||||||
| required(:start_ts).filled(:integer) | ||||||
| required(:end_ts).filled(:integer) | ||||||
| required(:period_interval).filled(:integer) | ||||||
| end | ||||||
| end | ||||||
| end | ||||||
|
|
||||||
| def fetch(params) | ||||||
| filter = EventFilter.new(EventFilter::Properties.new(**params)) | ||||||
| raise ArgumentError, filter.errors.full_messages.join(', ') unless filter.validate({}) | ||||||
|
|
||||||
| path = "#{filter.series_ticker}/events/#{filter.ticker}/candlesticks" | ||||||
| query_params = filter.to_h.slice('start_ts', 'end_ts', 'period_interval') | ||||||
|
||||||
| query_params = filter.to_h.slice('start_ts', 'end_ts', 'period_interval') | |
| query_params = filter.to_h.slice(:start_ts, :end_ts, :period_interval) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||
| # frozen_string_literal: true | ||||||
|
|
||||||
| module Rubyists | ||||||
| module Kalshi | ||||||
| module Series | ||||||
| # Event Forecast Percentile History API endpoint | ||||||
| class ForecastPercentileHistory < Kalshi::Endpoint | ||||||
| # Filter for Event Forecast Percentile History | ||||||
| class EventFilter < Kalshi::Contract | ||||||
| propertize(%i[series_ticker ticker percentiles start_ts end_ts period_interval]) | ||||||
|
|
||||||
| validation do | ||||||
| params do | ||||||
| required(:series_ticker).filled(:string) | ||||||
| required(:ticker).filled(:string) | ||||||
| required(:percentiles).filled(:array) | ||||||
| required(:start_ts).filled(:integer) | ||||||
| required(:end_ts).filled(:integer) | ||||||
| required(:period_interval).filled(:integer) | ||||||
| end | ||||||
| end | ||||||
| end | ||||||
|
|
||||||
| def fetch(params) | ||||||
| filter = EventFilter.new(EventFilter::Properties.new(**params)) | ||||||
| raise ArgumentError, filter.errors.full_messages.join(', ') unless filter.validate({}) | ||||||
|
|
||||||
| path = "#{filter.series_ticker}/events/#{filter.ticker}/forecast_percentile_history" | ||||||
| query_params = filter.to_h.slice('start_ts', 'end_ts', 'period_interval') | ||||||
|
||||||
| query_params = filter.to_h.slice('start_ts', 'end_ts', 'period_interval') | |
| query_params = filter.to_h.slice(:start_ts, :end_ts, :period_interval) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| require_relative '../../helper' | ||
|
|
||
| describe Rubyists::Kalshi::Events::Client do | ||
| let(:client) { Rubyists::Kalshi::Client.new } | ||
| let(:events_client) { client.events } | ||
| let(:base_url) { Rubyists::Kalshi.config.base_url } | ||
|
|
||
| describe '#list' do | ||
| it 'fetches the events list' do | ||
| stub_request(:get, "#{base_url}/events") | ||
| .to_return(status: 200, body: '{"events": []}', headers: { 'Content-Type' => 'application/json' }) | ||
|
|
||
| response = events_client.list | ||
|
|
||
| assert_equal({ events: [] }, response) | ||
| end | ||
| end | ||
|
|
||
| describe '#fetch' do | ||
| it 'fetches a specific event by ticker' do | ||
| ticker = 'KX-EVENT' | ||
| stub_request(:get, "#{base_url}/events/#{ticker}") | ||
| .to_return(status: 200, body: '{"event": {}}', headers: { 'Content-Type' => 'application/json' }) | ||
|
|
||
| response = events_client.fetch(ticker) | ||
|
|
||
| assert_equal({ event: {} }, response) | ||
| end | ||
| end | ||
|
|
||
| describe '#metadata' do | ||
| it 'fetches event metadata' do | ||
| ticker = 'KX-EVENT' | ||
| stub_request(:get, "#{base_url}/events/#{ticker}/metadata") | ||
| .to_return(status: 200, body: '{"metadata": {}}', headers: { 'Content-Type' => 'application/json' }) | ||
|
|
||
| response = events_client.metadata(ticker) | ||
|
|
||
| assert_equal({ metadata: {} }, response) | ||
| end | ||
| end | ||
|
|
||
| describe '#multivariate' do | ||
| it 'returns a Multivariate instance' do | ||
| assert_instance_of Rubyists::Kalshi::Events::Multivariate, events_client.multivariate | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| require_relative '../../helper' | ||
|
|
||
| describe Rubyists::Kalshi::Events::Multivariate do | ||
| let(:client) { Rubyists::Kalshi::Client.new } | ||
| let(:multivariate) { client.events.multivariate } | ||
| let(:base_url) { Rubyists::Kalshi.config.base_url } | ||
|
|
||
| describe '#list' do | ||
| it 'fetches the multivariate events list' do | ||
| stub_request(:get, "#{base_url}/events/multivariate") | ||
| .to_return(status: 200, body: '{"events": []}', headers: { 'Content-Type' => 'application/json' }) | ||
|
|
||
| response = multivariate.list | ||
|
|
||
| assert_equal({ events: [] }, response) | ||
| end | ||
|
|
||
| it 'fetches the multivariate events list with filters' do | ||
| stub_request(:get, "#{base_url}/events/multivariate") | ||
| .with(query: { series_ticker: 'KX-SERIES' }) | ||
| .to_return(status: 200, body: '{"events": []}', headers: { 'Content-Type' => 'application/json' }) | ||
|
|
||
| response = multivariate.list(series_ticker: 'KX-SERIES') | ||
|
|
||
| assert_equal({ events: [] }, response) | ||
| end | ||
| end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Events::Client methods should use memoization for consistency with the established pattern in Market::Client (lib/kalshi/market/client.rb:14-35). All methods in Market::Client use the ||= operator to cache instances. Consider adding memoization like
@multivariate ||= Multivariate.new(client)for the multivariate method.