Skip to content

Commit 5cece2c

Browse files
committed
helpers for intraday
1 parent 35719e2 commit 5cece2c

1 file changed

Lines changed: 150 additions & 22 deletions

File tree

src/systemathics/apis/helpers/dataframe_helpers.py

Lines changed: 150 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,24 @@
1111
import pandas as pd
1212
from datetime import date,datetime
1313
from google.type import date_pb2
14+
from google.type import datetime_pb2
1415

1516
from systemathics.apis.type.shared.v1 import asset_pb2 as asset
1617
from systemathics.apis.type.shared.v1 import constraints_pb2 as constraints
1718
from systemathics.apis.type.shared.v1 import date_interval_pb2 as date_interval
19+
import systemathics.apis.type.shared.v1.sampling_pb2 as sampling
1820
import systemathics.apis.type.shared.v1.identifier_pb2 as identifier
1921
import systemathics.apis.services.daily.v2.get_daily_pb2 as get_daily
2022
import systemathics.apis.services.daily.v2.get_daily_pb2_grpc as get_daily_service
23+
import systemathics.apis.services.intraday.v2.get_intraday_pb2 as get_intraday
24+
import systemathics.apis.services.intraday.v2.get_intraday_pb2_grpc as get_intraday_service
2125

2226
import systemathics.apis.helpers.token_helpers as token_helpers
2327
import systemathics.apis.helpers.channel_helpers as channel_helpers
2428

25-
def get_cds_index(ticker, start_date=None, end_date=None, batch=None, selected_fields=None, provider="Markit"):
29+
def get_cds_index_daily(ticker, start_date=None, end_date=None, batch=None, selected_fields=None, provider="Markit"):
2630
"""
27-
Fetch CDS data from gRPC API for a given ticker and date range.
31+
Fetch CDS Index daily data from gRPC API for a given ticker and date range.
2832
2933
Parameters:
3034
ticker (str): The ticker symbol
@@ -40,23 +44,7 @@ def get_cds_index(ticker, start_date=None, end_date=None, batch=None, selected_f
4044
pd.DataFrame: DataFrame with Date as index and all available fields as columns
4145
"""
4246

43-
def python_date_to_google_date(py_date):
44-
"""Convert Python date to Google Date protobuf message"""
45-
return date_pb2.Date(year=py_date.year, month=py_date.month, day=py_date.day)
46-
47-
# Helper function to parse date strings
48-
def parse_date_input(date_input):
49-
"""Convert string dates to date objects if needed."""
50-
if date_input is None:
51-
return None
52-
if isinstance(date_input, date):
53-
return python_date_to_google_date(date_input)
54-
if isinstance(date_input, datetime):
55-
return python_date_to_google_date(date_input.date())
56-
if isinstance(date_input, str):
57-
d = datetime.strptime(date_input, '%Y-%m-%d').date()
58-
return python_date_to_google_date(d)
59-
raise ValueError(f"Invalid date type: {type(date_input)}")
47+
6048

6149
# All available fields
6250
all_fields = [
@@ -88,9 +76,9 @@ def parse_date_input(date_input):
8876
# Create DateInterval with only the dates that are provided
8977
date_interval_kwargs = {}
9078
if start_date is not None:
91-
date_interval_kwargs['start_date'] = parse_date_input(start_date)
79+
date_interval_kwargs['start_date'] = _parse_date_input(start_date)
9280
if end_date is not None:
93-
date_interval_kwargs['end_date'] = parse_date_input(end_date)
81+
date_interval_kwargs['end_date'] = _parse_date_input(end_date)
9482

9583
constraints_obj = constraints.Constraints(
9684
date_intervals=[date_interval.DateInterval(**date_interval_kwargs)]
@@ -199,4 +187,144 @@ def parse_date_input(date_input):
199187
return pd.DataFrame()
200188
except Exception as e:
201189
print(f"Error: {str(e)}")
202-
return pd.DataFrame()
190+
return pd.DataFrame()
191+
192+
193+
194+
def get_cds_index_intraday(ticker, start_date=None, end_date=None, sampling=sampling.SAMPLING_ONE_MINUTE, selected_fields=None, provider="Markit"):
195+
"""
196+
Fetch CDS Index intraday data from gRPC API for a given ticker and date range.
197+
198+
Parameters:
199+
ticker (str): The ticker symbol
200+
start_date (datetime.date or str, optional): Start date for data retrieval.
201+
If None, set not limits
202+
end_date (datetime.date or str, optional): End date for data retrieval.
203+
If None, set not limits
204+
sampling (sampling, optional): Sampling perdiod for intrday. Default to one minute.
205+
selected_fields (list, optional): List of specific fields to retrieve.
206+
If None, gets all fields.
207+
provider (str): Data provider, default is "Markit"
208+
Returns:
209+
pd.DataFrame: DataFrame with Date as index and all available fields as columns
210+
"""
211+
212+
# All available fields
213+
all_fields = [
214+
'BidConventionalSpread',
215+
'BidPrice',
216+
'MidConventionalSpread',
217+
'MidPrice',
218+
'AskConventionalSpread',
219+
'AskPrice'
220+
]
221+
222+
# Use all fields if none specified, otherwise validate selected fields
223+
if selected_fields is None:
224+
fields = all_fields
225+
else:
226+
fields = [f for f in selected_fields if f in all_fields]
227+
if not fields:
228+
raise ValueError("No valid fields selected")
229+
230+
# Create identifier
231+
id = identifier.Identifier(
232+
asset_type=asset.AssetType.ASSET_TYPE_CDS_INDEX,
233+
ticker=ticker
234+
)
235+
id.provider.value = provider
236+
237+
# Build constraints only if we have at least one date
238+
constraints_obj = None
239+
if start_date is not None or end_date is not None:
240+
# Create DateInterval with only the dates that are provided
241+
date_interval_kwargs = {}
242+
if start_date is not None:
243+
date_interval_kwargs['start_date'] = _parse_date_input(start_date)
244+
if end_date is not None:
245+
date_interval_kwargs['end_date'] = _parse_date_input(end_date)
246+
constraints_obj = constraints.Constraints(
247+
date_intervals=[date_interval.DateInterval(**date_interval_kwargs)]
248+
)
249+
250+
# Create request with or without constraints
251+
request_kwargs = {
252+
'identifier': id,
253+
'fields': fields,
254+
'sampling': sampling
255+
}
256+
257+
if constraints_obj is not None:
258+
request_kwargs['constraints'] = constraints_obj
259+
try:
260+
# Open gRPC channel
261+
with channel_helpers.get_grpc_channel() as channel:
262+
# Send request and receive response
263+
token = token_helpers.get_token()
264+
first = True
265+
response = []
266+
info = None
267+
# Create service stub
268+
service = get_intraday_service.IntradayServiceStub(channel)
269+
scalar_request = get_intraday.IntradayRequest(**request_kwargs)
270+
271+
for data in service.IntradayScalarStream(request=scalar_request, metadata=[('authorization', token)]):
272+
if first:
273+
info = data
274+
first = False
275+
else:
276+
response.append(data.data)
277+
278+
# Process the response
279+
if not response or info is None:
280+
print("No data received")
281+
return pd.DataFrame()
282+
283+
# Get field indices
284+
available_fields = [f for f in info.info.fields]
285+
field_indices = {field: available_fields.index(field)
286+
for field in fields if field in available_fields}
287+
288+
# Extract dates
289+
dates = [datetime(d.datetime.year, d.datetime.month, d.datetime.day, d.datetime.hours, d.datetime.minutes, d.datetime.seconds) for d in response]
290+
291+
# Create dictionary for DataFrame
292+
data_dict = {}
293+
294+
# Extract data for each field
295+
for field_name, field_index in field_indices.items():
296+
data_dict[field_name] = [b.data[field_index] for b in response]
297+
298+
# Create DataFrame
299+
df = pd.DataFrame(data_dict, index=dates)
300+
df.index.name = 'Datetime'
301+
302+
# Sort by date for better readability
303+
df = df.sort_index()
304+
return df
305+
306+
except grpc.RpcError as e:
307+
print(f"gRPC Error: {e.code().name}")
308+
print(f"Details: {e.details()}")
309+
return pd.DataFrame()
310+
except Exception as e:
311+
print(f"Error: {str(e)}")
312+
return pd.DataFrame()
313+
314+
def _python_date_to_google_date(py_date):
315+
"""Convert Python date to Google Date protobuf message"""
316+
return date_pb2.Date(year=py_date.year, month=py_date.month, day=py_date.day)
317+
318+
# Helper function to parse date strings
319+
def _parse_date_input(date_input):
320+
"""Convert string dates to date objects if needed."""
321+
if date_input is None:
322+
return None
323+
if isinstance(date_input, date):
324+
return _python_date_to_google_date(date_input)
325+
if isinstance(date_input, datetime):
326+
return _python_date_to_google_date(date_input.date())
327+
if isinstance(date_input, str):
328+
d = datetime.strptime(date_input, '%Y-%m-%d').date()
329+
return _python_date_to_google_date(d)
330+
raise ValueError(f"Invalid date type: {type(date_input)}")

0 commit comments

Comments
 (0)