1111import pandas as pd
1212from datetime import date ,datetime
1313from google .type import date_pb2
14+ from google .type import datetime_pb2
1415
1516from systemathics .apis .type .shared .v1 import asset_pb2 as asset
1617from systemathics .apis .type .shared .v1 import constraints_pb2 as constraints
1718from systemathics .apis .type .shared .v1 import date_interval_pb2 as date_interval
19+ import systemathics .apis .type .shared .v1 .sampling_pb2 as sampling
1820import systemathics .apis .type .shared .v1 .identifier_pb2 as identifier
1921import systemathics .apis .services .daily .v2 .get_daily_pb2 as get_daily
2022import 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
2226import systemathics .apis .helpers .token_helpers as token_helpers
2327import 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