Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion docs/source/Snapshot.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ Get crypto L2 book snapshot

.. automethod:: massive.RESTClient.get_snapshot_crypto_book

=================================
Get indices snapshot
=================================

- `Indices snapshot`_

.. automethod:: massive.RESTClient.list_snapshot_indices

.. automethod:: massive.RESTClient.get_snapshot_indices

.. _Stocks snapshot all tickers: https://massive.com/docs/stocks/get_v3_snapshot
.. _Options snapshot all tickers: https://massive.com/docs/options/get_v3_snapshot
.. _Forex snapshot all tickers: https://massive.com/docs/forex/get_v3_snapshot
Expand All @@ -75,4 +85,5 @@ Get crypto L2 book snapshot
.. _Forex snapshot ticker: https://massive.com/docs/forex/get_v2_snapshot_locale_global_markets_forex_tickers__ticker
.. _Crypto snapshot ticker: https://massive.com/docs/crypto/get_v2_snapshot_locale_global_markets_crypto_tickers__ticker
.. _Options snapshot option contract: https://massive.com/docs/options/get_v3_snapshot_options__underlyingasset___optioncontract
.. _Crypto snapshot ticker full book (L2): https://massive.com/docs/crypto/get_v2_snapshot_locale_global_markets_crypto_tickers__ticker__book
.. _Crypto snapshot ticker full book (L2): https://massive.com/docs/crypto/get_v2_snapshot_locale_global_markets_crypto_tickers__ticker__book
.. _Indices snapshot: https://massive.com/docs/indices/get_v3_snapshot_indices
16 changes: 16 additions & 0 deletions examples/rest/indices-snapshots_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from massive import RESTClient

# docs
# https://massive.com/docs/indices/get_v3_snapshot_indices
# https://github.com/massive-com/client-python/blob/master/massive/rest/snapshot.py#

# client = RESTClient("XXXXXX") # hardcoded api_key is used
client = RESTClient() # MASSIVE_API_KEY environment variable is used

# list_snapshot_indices follows pagination, so this iterates over every index
snapshots = []
for s in client.list_snapshot_indices(limit=250):
snapshots.append(s)

print(len(snapshots))
print(snapshots[0])
4 changes: 4 additions & 0 deletions massive/rest/models/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class IndicesSnapshot:
session: Optional[IndicesSession] = None
error: Optional[str] = None
message: Optional[str] = None
last_updated: Optional[int] = None
timeframe: Optional[str] = None

@staticmethod
def from_dict(d):
Expand All @@ -81,6 +83,8 @@ def from_dict(d):
),
error=d.get("error", None),
message=d.get("message", None),
last_updated=d.get("last_updated", None),
timeframe=d.get("timeframe", None),
)


Expand Down
55 changes: 55 additions & 0 deletions massive/rest/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,17 @@ def get_snapshot_indices(
raw: bool = False,
options: Optional[RequestOptionBuilder] = None,
) -> Union[List[IndicesSnapshot], HTTPResponse]:
"""
Get snapshots for indices. Returns a single page of results; use
list_snapshot_indices to paginate through all of them.
- https://massive.com/docs/indices/get_v3_snapshot_indices

:param ticker_any_of: Comma-separated list of tickers, up to a maximum of 250.
:param params: Any additional query params
:param raw: returns the raw HTTP response if true, else the response is deserialized into a structured object
:param options: request options
:return: list of IndicesSnapshot
"""
url = f"/v3/snapshot/indices"

return self._get(
Expand All @@ -254,3 +265,47 @@ def get_snapshot_indices(
result_key="results",
options=options,
)

def list_snapshot_indices(
self,
ticker: Optional[str] = None,
ticker_any_of: Optional[Union[str, List[str]]] = None,
ticker_lt: Optional[str] = None,
ticker_lte: Optional[str] = None,
ticker_gt: Optional[str] = None,
ticker_gte: Optional[str] = None,
order: Optional[Union[str, Order]] = None,
limit: Optional[int] = None,
sort: Optional[str] = None,
params: Optional[Dict[str, Any]] = None,
raw: bool = False,
options: Optional[RequestOptionBuilder] = None,
) -> Union[Iterator[IndicesSnapshot], HTTPResponse]:
"""
Get snapshots for indices, following pagination.
- https://massive.com/docs/indices/get_v3_snapshot_indices

:param ticker: A single index ticker, e.g. I:SPX.
:param ticker_any_of: Comma-separated list of tickers, up to a maximum of 250. If no tickers are passed then all
results will be returned in a paginated manner.
:param ticker_lt: search for tickers less than
:param ticker_lte: search for tickers less than or equal to
:param ticker_gt: search for tickers greater than
:param ticker_gte: search for tickers greater than or equal to
:param order: Order results based on the sort field.
:param limit: Limit the size of the response per-page, max is 250.
:param sort: Sort field used for ordering. Default is ticker.
:param params: Any additional query params
:param raw: returns the raw HTTP response if true, else the response is deserialized into a structured object
:param options: request options
:return: iterator of IndicesSnapshot
"""
url = f"/v3/snapshot/indices"
return self._paginate(
path=url,
params=self._get_params(self.list_snapshot_indices, locals()),
result_key="results",
deserializer=IndicesSnapshot.from_dict,
raw=raw,
options=options,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"results": [
{
"value": 28.685000000000002,
"last_updated": 1792081393146000000,
"timeframe": "REAL-TIME",
"name": "PROSHARES ULTRA BASIC MATERIALS ETF",
"ticker": "I:UYMIV",
"market_status": "regular_trading",
"type": "indices",
"session": {
"change": 0.924,
"change_percent": 3.328,
"close": 28.6859,
"high": 29.0102,
"low": 27.8834,
"open": 27.8855,
"previous_close": 27.761200000000002
}
},
{
"value": 19.25,
"last_updated": 1792008000219000000,
"timeframe": "REAL-TIME",
"name": "Cboe VIX Jan Futures 4pm EST Mark Index",
"ticker": "I:UZF",
"market_status": "regular_trading",
"type": "indices",
"session": {
"change": 0,
"change_percent": 0,
"close": 19.25,
"high": 19.25,
"low": 19.25,
"open": 19.25,
"previous_close": 19.25
}
}
],
"status": "OK",
"request_id": "0ade2056b75a64c1bbf1fe9fca8f20ed"
}
43 changes: 43 additions & 0 deletions test_rest/mocks/v3/snapshot/indices&ticker.gte=I%3ASPX.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"results": [
{
"value": 7717.17,
"last_updated": 1792081393031000000,
"timeframe": "REAL-TIME",
"name": "Standard & Poor's 500",
"ticker": "I:SPX",
"market_status": "regular_trading",
"type": "indices",
"session": {
"change": -1.77,
"change_percent": -0.0229,
"close": 7718.56,
"high": 7738.21,
"low": 7669.66,
"open": 7687.31,
"previous_close": 7718.9400000000005
}
},
{
"value": 82.5721,
"last_updated": 1792081393415000000,
"timeframe": "REAL-TIME",
"name": "PROSHARES S&P 500 EX-ENERGY ETF",
"ticker": "I:SPXEIV",
"market_status": "regular_trading",
"type": "indices",
"session": {
"change": 0.0058,
"change_percent": 0.00702,
"close": 82.583,
"high": 82.8018,
"low": 81.96520000000001,
"open": 81.96520000000001,
"previous_close": 82.5663
}
}
],
"status": "OK",
"request_id": "62a572d0d04de8a7001f3c01a6d861ad",
"next_url": "https://api.massive.com/v3/snapshot/indices?cursor=bGltaXQ9MTAmc29ydD10aWNrZXImdGlja2VyLmd0PUklM0FVWUdJViZ0aWNrZXIubHRlPQ"
}
82 changes: 82 additions & 0 deletions test_rest/test_snapshots.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,88 @@ def test_get_snapshot_crypto_book(self):
)
self.assertEqual(snapshots, expected)

def test_list_snapshot_indices(self):
# two pages: the first page's next_url points at the second
snapshots = [s for s in self.c.list_snapshot_indices(ticker_gte="I:SPX")]
expected = [
IndicesSnapshot(
value=7717.17,
name="Standard & Poor's 500",
type="indices",
ticker="I:SPX",
market_status="regular_trading",
session=IndicesSession(
change=-1.77,
change_percent=-0.0229,
close=7718.56,
high=7738.21,
low=7669.66,
open=7687.31,
previous_close=7718.9400000000005,
),
last_updated=1792081393031000000,
timeframe="REAL-TIME",
),
IndicesSnapshot(
value=82.5721,
name="PROSHARES S&P 500 EX-ENERGY ETF",
type="indices",
ticker="I:SPXEIV",
market_status="regular_trading",
session=IndicesSession(
change=0.0058,
change_percent=0.00702,
close=82.583,
high=82.8018,
low=81.96520000000001,
open=81.96520000000001,
previous_close=82.5663,
),
last_updated=1792081393415000000,
timeframe="REAL-TIME",
),
IndicesSnapshot(
value=28.685000000000002,
name="PROSHARES ULTRA BASIC MATERIALS ETF",
type="indices",
ticker="I:UYMIV",
market_status="regular_trading",
session=IndicesSession(
change=0.924,
change_percent=3.328,
close=28.6859,
high=29.0102,
low=27.8834,
open=27.8855,
previous_close=27.761200000000002,
),
last_updated=1792081393146000000,
timeframe="REAL-TIME",
),
IndicesSnapshot(
value=19.25,
name="Cboe VIX Jan Futures 4pm EST Mark Index",
type="indices",
ticker="I:UZF",
market_status="regular_trading",
session=IndicesSession(
change=0,
change_percent=0,
close=19.25,
high=19.25,
low=19.25,
open=19.25,
previous_close=19.25,
),
last_updated=1792008000219000000,
timeframe="REAL-TIME",
),
]
self.assertEqual(snapshots, expected)
# modelclass drops unknown kwargs, so check the fields exist explicitly
self.assertEqual(snapshots[0].last_updated, 1792081393031000000)
self.assertEqual(snapshots[0].timeframe, "REAL-TIME")

def test_get_snapshot_indices(self):
ticker_any_of = ["SPX", "APx", "APy"]
summary_results = self.c.get_snapshot_indices(ticker_any_of)
Expand Down
Loading