1010 get_index_tick - Get Index tick data as a DataFrame using Ganymede gRPC API.
1111 get_future_daily - Get future daily data as a DataFrame using Ganymede gRPC API.
1212 get_equity_daily - Get equity daily data as a DataFrame using Ganymede gRPC API.
13+ get_equity_intraday - Get equity intraday data as a DataFrame using Ganymede gRPC API.
14+ get_future_intraday - Get future intraday data as a DataFrame using Ganymede gRPC API.
1315 get_cds_index_option_daily - Get CDS Index option daily data as a DataFrame using Ganymede gRPC API.
1416 get_cds_index_option_by_underlier - Get CDS Index option data filtered by underlier as a DataFrame using Ganymede gRPC API.
1517"""
2527from systemathics .apis .type .shared .v1 import asset_pb2 as asset
2628from systemathics .apis .type .shared .v1 import constraints_pb2 as constraints
2729from systemathics .apis .type .shared .v1 import date_interval_pb2 as date_interval
30+ from systemathics .apis .type .shared .v1 import time_interval_pb2 as time_interval
31+ from google .type import timeofday_pb2 as timeofday
2832import systemathics .apis .type .shared .v1 .sampling_pb2 as sampling
2933import systemathics .apis .type .shared .v1 .identifier_pb2 as identifier
3034import systemathics .apis .services .daily .v1 .daily_bars_pb2 as daily_bars
35+ import systemathics .apis .services .intraday .v1 .intraday_bars_pb2 as intraday_bars
36+ import systemathics .apis .services .intraday .v1 .intraday_bars_pb2_grpc as intraday_bars_service
3137import systemathics .apis .services .daily .v1 .daily_bars_pb2_grpc as daily_bars_service
3238import systemathics .apis .services .daily .v2 .get_daily_pb2 as get_daily
3339import systemathics .apis .services .daily .v2 .get_daily_pb2_grpc as get_daily_service
@@ -1266,6 +1272,216 @@ def _parse_date_for_filtering(date_input):
12661272 print (f"Error: { str (e )} " )
12671273 return pd .DataFrame ()
12681274
1275+ def get_equity_intraday (ticker , start_date = None , end_date = None , start_time = None , end_time = None , sampling = sampling .SAMPLING_ONE_MINUTE , provider = "FirstRateData" ):
1276+ """
1277+ Fetch Equity intraday data from gRPC API for a given ticker and optionally filter by date/time range.
1278+
1279+ Parameters:
1280+ ticker (str): The ticker symbol
1281+ start_date (datetime.date or str, optional): Start date for data retrieval (format: '2025-05-28').
1282+ If None, no start limit is applied
1283+ end_date (datetime.date or str, optional): End date for data retrieval (format: '2025-05-28').
1284+ If None, no end limit is applied
1285+ start_time (datetime.time or str, optional): Start time filter (format: 'HH:MM' or 'HH:MM:SS').
1286+ If None, no start time limit is applied
1287+ end_time (datetime.time or str, optional): End time filter (format: 'HH:MM' or 'HH:MM:SS').
1288+ If None, no end time limit is applied
1289+ sampling (sampling, optional): Sampling period for intraday. Default to one minute.
1290+ provider (str): Data provider, default is "FirstRateData"
1291+
1292+ # Example usage:
1293+ # df = get_equity_intraday('AAPL US Equity') # Get all available data
1294+ # df = get_equity_intraday('AAPL US Equity', start_date='2024-01-01') # From Jan 1, 2024 onwards
1295+ # df = get_equity_intraday('AAPL US Equity', start_date='2024-01-01', end_date='2024-12-31') # Full year 2024
1296+ # df = get_equity_intraday('AAPL US Equity', start_date='2024-01-01', start_time='09:30', end_time='16:00') # With time filter
1297+
1298+ Returns:
1299+ pd.DataFrame: DataFrame with Datetime as index and OHLCV + count/vwap as columns
1300+ """
1301+
1302+ id = identifier .Identifier (
1303+ ticker = ticker ,
1304+ asset_type = asset .AssetType .ASSET_TYPE_EQUITY
1305+ )
1306+ id .provider .value = provider
1307+
1308+ # Build date interval if dates are provided
1309+ date_interval_obj = None
1310+ if start_date is not None or end_date is not None :
1311+ date_interval_kwargs = {}
1312+ if start_date is not None :
1313+ date_interval_kwargs ['start_date' ] = _parse_date_input (start_date )
1314+ if end_date is not None :
1315+ date_interval_kwargs ['end_date' ] = _parse_date_input (end_date )
1316+ date_interval_obj = date_interval .DateInterval (** date_interval_kwargs )
1317+
1318+ # Build time interval if times are provided
1319+ time_interval_obj = None
1320+ if start_time is not None or end_time is not None :
1321+ time_interval_kwargs = {}
1322+ if start_time is not None :
1323+ time_interval_kwargs ['start_time' ] = _parse_time_input (start_time )
1324+ if end_time is not None :
1325+ time_interval_kwargs ['end_time' ] = _parse_time_input (end_time )
1326+ time_interval_obj = time_interval .TimeInterval (** time_interval_kwargs )
1327+
1328+ request_kwargs = {
1329+ 'identifier' : id ,
1330+ 'sampling' : sampling ,
1331+ }
1332+ if date_interval_obj is not None :
1333+ request_kwargs ['date_interval' ] = date_interval_obj
1334+ if time_interval_obj is not None :
1335+ request_kwargs ['time_interval' ] = time_interval_obj
1336+
1337+ request = intraday_bars .IntradayBarsRequest (** request_kwargs )
1338+
1339+ try :
1340+ with channel_helpers .get_grpc_channel () as channel :
1341+ token = token_helpers .get_token ()
1342+ service = intraday_bars_service .IntradayBarsServiceStub (channel )
1343+ response = service .IntradayBars (request = request , metadata = [('authorization' , token )])
1344+
1345+ if not response or not response .data :
1346+ print ("No data received" )
1347+ return pd .DataFrame ()
1348+
1349+ rows = []
1350+ for b in response .data :
1351+ row = {
1352+ "Datetime" : pd .Timestamp (b .time_stamp .seconds , unit = 's' ),
1353+ "Open" : b .open ,
1354+ "High" : b .high ,
1355+ "Low" : b .low ,
1356+ "Close" : b .close ,
1357+ "Volume" : b .volume ,
1358+ "Count" : b .count ,
1359+ "Vwap" : b .vwap ,
1360+ }
1361+ rows .append (row )
1362+
1363+ if not rows :
1364+ print ("No data received." )
1365+ return pd .DataFrame ()
1366+
1367+ return (
1368+ pd .DataFrame (rows )
1369+ .set_index ("Datetime" )
1370+ .sort_index ()
1371+ )
1372+
1373+ except grpc .RpcError as e :
1374+ print (f"gRPC Error [{ e .code ().name } ]: { e .details ()} " )
1375+ return pd .DataFrame ()
1376+ except Exception as e :
1377+ print (f"Error: { e } " )
1378+ return pd .DataFrame ()
1379+
1380+ def get_future_intraday (ticker , start_date = None , end_date = None , start_time = None , end_time = None , sampling = sampling .SAMPLING_ONE_MINUTE , provider = "FirstRateData" ):
1381+ """
1382+ Fetch Future intraday data from gRPC API for a given ticker and optionally filter by date/time range.
1383+
1384+ Parameters:
1385+ ticker (str): The ticker symbol
1386+ start_date (datetime.date or str, optional): Start date for data retrieval (format: '2025-05-28').
1387+ If None, no start limit is applied
1388+ end_date (datetime.date or str, optional): End date for data retrieval (format: '2025-05-28').
1389+ If None, no end limit is applied
1390+ start_time (datetime.time or str, optional): Start time filter (format: 'HH:MM' or 'HH:MM:SS').
1391+ If None, no start time limit is applied
1392+ end_time (datetime.time or str, optional): End time filter (format: 'HH:MM' or 'HH:MM:SS').
1393+ If None, no end time limit is applied
1394+ sampling (sampling, optional): Sampling period for intraday. Default to one minute.
1395+ provider (str): Data provider, default is "FirstRateData"
1396+
1397+ # Example usage:
1398+ # df = get_future_intraday('CL1 Comdty') # Get all available data
1399+ # df = get_future_intraday('CL1 Comdty', start_date='2024-01-01') # From Jan 1, 2024 onwards
1400+ # df = get_future_intraday('CL1 Comdty', start_date='2024-01-01', end_date='2024-12-31') # Full year 2024
1401+ # df = get_future_intraday('CL1 Comdty', start_date='2024-01-01', start_time='09:30', end_time='16:00') # With time filter
1402+
1403+ Returns:
1404+ pd.DataFrame: DataFrame with Datetime as index and OHLCV + count/vwap as columns
1405+ """
1406+
1407+ id = identifier .Identifier (
1408+ ticker = ticker ,
1409+ asset_type = asset .AssetType .ASSET_TYPE_FUTURE
1410+ )
1411+ id .provider .value = provider
1412+
1413+ # Build date interval if dates are provided
1414+ date_interval_obj = None
1415+ if start_date is not None or end_date is not None :
1416+ date_interval_kwargs = {}
1417+ if start_date is not None :
1418+ date_interval_kwargs ['start_date' ] = _parse_date_input (start_date )
1419+ if end_date is not None :
1420+ date_interval_kwargs ['end_date' ] = _parse_date_input (end_date )
1421+ date_interval_obj = date_interval .DateInterval (** date_interval_kwargs )
1422+
1423+ # Build time interval if times are provided
1424+ time_interval_obj = None
1425+ if start_time is not None or end_time is not None :
1426+ time_interval_kwargs = {}
1427+ if start_time is not None :
1428+ time_interval_kwargs ['start_time' ] = _parse_time_input (start_time )
1429+ if end_time is not None :
1430+ time_interval_kwargs ['end_time' ] = _parse_time_input (end_time )
1431+ time_interval_obj = time_interval .TimeInterval (** time_interval_kwargs )
1432+
1433+ request_kwargs = {
1434+ 'identifier' : id ,
1435+ 'sampling' : sampling ,
1436+ }
1437+ if date_interval_obj is not None :
1438+ request_kwargs ['date_interval' ] = date_interval_obj
1439+ if time_interval_obj is not None :
1440+ request_kwargs ['time_interval' ] = time_interval_obj
1441+
1442+ request = intraday_bars .IntradayBarsRequest (** request_kwargs )
1443+
1444+ try :
1445+ with channel_helpers .get_grpc_channel () as channel :
1446+ token = token_helpers .get_token ()
1447+ service = intraday_bars_service .IntradayBarsServiceStub (channel )
1448+ response = service .IntradayBars (request = request , metadata = [('authorization' , token )])
1449+
1450+ if not response or not response .data :
1451+ print ("No data received" )
1452+ return pd .DataFrame ()
1453+
1454+ rows = []
1455+ for b in response .data :
1456+ row = {
1457+ "Datetime" : pd .Timestamp (b .time_stamp .seconds , unit = 's' ),
1458+ "Open" : b .open ,
1459+ "High" : b .high ,
1460+ "Low" : b .low ,
1461+ "Close" : b .close ,
1462+ "Volume" : b .volume ,
1463+ "Count" : b .count ,
1464+ "Vwap" : b .vwap ,
1465+ }
1466+ rows .append (row )
1467+
1468+ if not rows :
1469+ print ("No data received." )
1470+ return pd .DataFrame ()
1471+
1472+ return (
1473+ pd .DataFrame (rows )
1474+ .set_index ("Datetime" )
1475+ .sort_index ()
1476+ )
1477+
1478+ except grpc .RpcError as e :
1479+ print (f"gRPC Error [{ e .code ().name } ]: { e .details ()} " )
1480+ return pd .DataFrame ()
1481+ except Exception as e :
1482+ print (f"Error: { e } " )
1483+ return pd .DataFrame ()
1484+
12691485
12701486# Helpers functions
12711487
@@ -1288,6 +1504,31 @@ def _parse_date_input(date_input):
12881504
12891505 raise ValueError (f"Invalid date type: { type (date_input )} " )
12901506
1507+
1508+ def _parse_time_input (time_input ):
1509+ """Convert string or datetime.time to Google TimeOfDay protobuf message.
1510+
1511+ Accepts:
1512+ - datetime.time object
1513+ - str in 'HH:MM' or 'HH:MM:SS' format
1514+ """
1515+ if time_input is None :
1516+ return None
1517+ if isinstance (time_input , datetime ):
1518+ t = time_input .time ()
1519+ return timeofday .TimeOfDay (hours = t .hour , minutes = t .minute , seconds = t .second )
1520+ from datetime import time as time_type
1521+ if isinstance (time_input , time_type ):
1522+ return timeofday .TimeOfDay (hours = time_input .hour , minutes = time_input .minute , seconds = time_input .second )
1523+ if isinstance (time_input , str ):
1524+ parts = time_input .split (':' )
1525+ h = int (parts [0 ])
1526+ m = int (parts [1 ]) if len (parts ) > 1 else 0
1527+ s = int (parts [2 ]) if len (parts ) > 2 else 0
1528+ return timeofday .TimeOfDay (hours = h , minutes = m , seconds = s )
1529+ raise ValueError (f"Invalid time type: { type (time_input )} " )
1530+
1531+
12911532def _build_strike_filter (strike ) -> "filter.DoubleFilter" :
12921533 """
12931534 Build a DoubleFilter proto from a Python value.
0 commit comments