Skip to content

Commit c5f9976

Browse files
committed
use dict to build dataframe
1 parent 109c082 commit c5f9976

1 file changed

Lines changed: 115 additions & 75 deletions

File tree

src/systemathics/apis/helpers/dataframe_helpers.py

Lines changed: 115 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -876,24 +876,32 @@ def get_cds_index_intraday(ticker, start_date=None, end_date=None, sampling=samp
876876
field_indices = {field: available_fields.index(field)
877877
for field in fields if field in available_fields}
878878

879-
# Extract dates
880-
dates = [datetime(d.datetime.year, d.datetime.month, d.datetime.day, d.datetime.hours, d.datetime.minutes, d.datetime.seconds) for d in response]
879+
rows = []
880+
for d in response:
881+
row = {
882+
"Datetime": pd.Timestamp(
883+
year=d.datetime.year,
884+
month=d.datetime.month,
885+
day=d.datetime.day,
886+
hour=d.datetime.hours,
887+
minute=d.datetime.minutes,
888+
second=d.datetime.seconds,
889+
),
890+
}
891+
for field_name, field_index in field_indices.items():
892+
row[field_name] = d.data[field_index]
893+
rows.append(row)
881894

882-
# Create dictionary for DataFrame
883-
data_dict = {}
884-
885-
# Extract data for each field
886-
for field_name, field_index in field_indices.items():
887-
data_dict[field_name] = [b.data[field_index] for b in response]
895+
if not rows:
896+
print("No data received.")
897+
return pd.DataFrame()
888898

889-
# Create DataFrame
890-
df = pd.DataFrame(data_dict, index=dates)
891-
df.index.name = 'Datetime'
899+
return (
900+
pd.DataFrame(rows)
901+
.set_index("Datetime")
902+
.sort_index()
903+
)
892904

893-
# Sort by date for better readability
894-
df = df.sort_index()
895-
return df
896-
897905
except grpc.RpcError as e:
898906
print(f"gRPC Error: {e.code().name}")
899907
print(f"Details: {e.details()}")
@@ -1000,24 +1008,32 @@ def get_cds_intraday(ticker, start_date=None, end_date=None, sampling=sampling.S
10001008
field_indices = {field: available_fields.index(field)
10011009
for field in fields if field in available_fields}
10021010

1003-
# Extract dates
1004-
dates = [datetime(d.datetime.year, d.datetime.month, d.datetime.day, d.datetime.hours, d.datetime.minutes, d.datetime.seconds) for d in response]
1011+
rows = []
1012+
for d in response:
1013+
row = {
1014+
"Datetime": pd.Timestamp(
1015+
year=d.datetime.year,
1016+
month=d.datetime.month,
1017+
day=d.datetime.day,
1018+
hour=d.datetime.hours,
1019+
minute=d.datetime.minutes,
1020+
second=d.datetime.seconds,
1021+
),
1022+
}
1023+
for field_name, field_index in field_indices.items():
1024+
row[field_name] = d.data[field_index]
1025+
rows.append(row)
10051026

1006-
# Create dictionary for DataFrame
1007-
data_dict = {}
1008-
1009-
# Extract data for each field
1010-
for field_name, field_index in field_indices.items():
1011-
data_dict[field_name] = [b.data[field_index] for b in response]
1027+
if not rows:
1028+
print("No data received.")
1029+
return pd.DataFrame()
10121030

1013-
# Create DataFrame
1014-
df = pd.DataFrame(data_dict, index=dates)
1015-
df.index.name = 'Datetime'
1031+
return (
1032+
pd.DataFrame(rows)
1033+
.set_index("Datetime")
1034+
.sort_index()
1035+
)
10161036

1017-
# Sort by date for better readability
1018-
df = df.sort_index()
1019-
return df
1020-
10211037
except grpc.RpcError as e:
10221038
print(f"gRPC Error: {e.code().name}")
10231039
print(f"Details: {e.details()}")
@@ -1083,41 +1099,53 @@ def _parse_date_for_filtering(date_input):
10831099
print("No data received")
10841100
return pd.DataFrame()
10851101

1086-
dates = [datetime(b.date.year, b.date.month, b.date.day) for b in response.data]
1087-
opens = [b.open for b in response.data]
1088-
highs = [b.high for b in response.data]
1089-
lows = [b.low for b in response.data]
1090-
closes = [b.close for b in response.data]
1091-
volumes = [b.volume for b in response.data]
1092-
1093-
data_dict = {'Date': dates, 'Open': opens, 'High': highs, 'Low': lows, 'Close': closes, 'Volume': volumes}
1094-
df = pd.DataFrame(data=data_dict)
1095-
df = df.set_index('Date')
1096-
1097-
# Sort by date for better readability
1098-
df = df.sort_index()
1099-
1102+
rows = []
1103+
for b in response.data:
1104+
row = {
1105+
"Date": pd.Timestamp(
1106+
year=b.date.year,
1107+
month=b.date.month,
1108+
day=b.date.day,
1109+
),
1110+
"Open": b.open,
1111+
"High": b.high,
1112+
"Low": b.low,
1113+
"Close": b.close,
1114+
"Volume": b.volume,
1115+
}
1116+
rows.append(row)
1117+
1118+
if not rows:
1119+
print("No data received.")
1120+
return pd.DataFrame()
1121+
1122+
df = (
1123+
pd.DataFrame(rows)
1124+
.set_index("Date")
1125+
.sort_index()
1126+
)
1127+
11001128
# Apply date filtering if specified
11011129
if start_date is not None or end_date is not None:
11021130
# Parse date inputs
11031131
if start_date is not None:
11041132
start_date_parsed = _parse_date_for_filtering(start_date)
11051133
start_datetime = datetime.combine(start_date_parsed, datetime.min.time())
1106-
1134+
11071135
if end_date is not None:
11081136
end_date_parsed = _parse_date_for_filtering(end_date)
11091137
end_datetime = datetime.combine(end_date_parsed, datetime.max.time())
1110-
1138+
11111139
# Filter the DataFrame
11121140
if start_date is not None and end_date is not None:
11131141
df = df[(df.index >= start_datetime) & (df.index <= end_datetime)]
11141142
elif start_date is not None:
11151143
df = df[df.index >= start_datetime]
11161144
elif end_date is not None:
11171145
df = df[df.index <= end_datetime]
1118-
1146+
11191147
return df
1120-
1148+
11211149
except grpc.RpcError as e:
11221150
print(f"gRPC Error: {e.code().name}")
11231151
print(f"Details: {e.details()}")
@@ -1129,25 +1157,25 @@ def _parse_date_for_filtering(date_input):
11291157
def get_equity_daily(ticker, start_date=None, end_date=None, provider="FirstRateData"):
11301158
"""
11311159
Fetch Equity daily data from gRPC API for a given ticker and optionally filter by date range.
1132-
1160+
11331161
Parameters:
11341162
ticker (str): The ticker symbol
1135-
start_date (datetime.date or str, optional): Start date for data retrieval (format: '2025-05-28').
1163+
start_date (datetime.date or str, optional): Start date for data retrieval (format: '2025-05-28').
11361164
If None, no start limit is applied
11371165
end_date (datetime.date or str, optional): End date for data retrieval (format: '2025-05-28').
11381166
If None, no end limit is applied
11391167
provider (str): Data provider, default is "FirstRateData"
11401168
11411169
# Example usage:
11421170
# df = get_equity_daily('AAPL US Equity') # Get all available data
1143-
# df = get_equity_daily('AAPL US Equity', start_date='2024-01-01') # From Jan 1, 2024 onwards
1171+
# df = get_equity_daily('AAPL US Equity', start_date='2024-01-01') # From Jan 1, 2024 onwards
11441172
# df = get_equity_daily('AAPL US Equity', end_date='2024-12-31') # Up to Dec 31, 2024
11451173
# df = get_equity_daily('AAPL US Equity', start_date='2024-01-01', end_date='2024-12-31') # Full year 2024
1146-
1174+
11471175
Returns:
11481176
pd.DataFrame: DataFrame with Date as index and all available fields as columns
11491177
"""
1150-
1178+
11511179
def _parse_date_for_filtering(date_input):
11521180
"""Parse date input for DataFrame filtering (returns date object, not Google date)"""
11531181
if date_input is None:
@@ -1159,13 +1187,13 @@ def _parse_date_for_filtering(date_input):
11591187
if isinstance(date_input, str):
11601188
return datetime.strptime(date_input, '%Y-%m-%d').date()
11611189
raise ValueError(f"Invalid date type: {type(date_input)}")
1162-
1190+
11631191
id = identifier.Identifier(
1164-
ticker=ticker,
1192+
ticker=ticker,
11651193
asset_type=asset.AssetType.ASSET_TYPE_EQUITY
11661194
)
11671195
id.provider.value = provider
1168-
1196+
11691197
request = daily_bars.DailyBarsRequest(identifier=id)
11701198

11711199
try:
@@ -1182,42 +1210,54 @@ def _parse_date_for_filtering(date_input):
11821210
if not response or not response.data:
11831211
print("No data received")
11841212
return pd.DataFrame()
1185-
1186-
dates = [datetime(b.date.year, b.date.month, b.date.day) for b in response.data]
1187-
opens = [b.open for b in response.data]
1188-
highs = [b.high for b in response.data]
1189-
lows = [b.low for b in response.data]
1190-
closes = [b.close for b in response.data]
1191-
volumes = [b.volume for b in response.data]
1192-
1193-
data_dict = {'Date': dates, 'Open': opens, 'High': highs, 'Low': lows, 'Close': closes, 'Volume': volumes}
1194-
df = pd.DataFrame(data=data_dict)
1195-
df = df.set_index('Date')
1196-
1197-
# Sort by date for better readability
1198-
df = df.sort_index()
1199-
1213+
1214+
rows = []
1215+
for b in response.data:
1216+
row = {
1217+
"Date": pd.Timestamp(
1218+
year=b.date.year,
1219+
month=b.date.month,
1220+
day=b.date.day,
1221+
),
1222+
"Open": b.open,
1223+
"High": b.high,
1224+
"Low": b.low,
1225+
"Close": b.close,
1226+
"Volume": b.volume,
1227+
}
1228+
rows.append(row)
1229+
1230+
if not rows:
1231+
print("No data received.")
1232+
return pd.DataFrame()
1233+
1234+
df = (
1235+
pd.DataFrame(rows)
1236+
.set_index("Date")
1237+
.sort_index()
1238+
)
1239+
12001240
# Apply date filtering if specified
12011241
if start_date is not None or end_date is not None:
12021242
# Parse date inputs
12031243
if start_date is not None:
12041244
start_date_parsed = _parse_date_for_filtering(start_date)
12051245
start_datetime = datetime.combine(start_date_parsed, datetime.min.time())
1206-
1246+
12071247
if end_date is not None:
12081248
end_date_parsed = _parse_date_for_filtering(end_date)
12091249
end_datetime = datetime.combine(end_date_parsed, datetime.max.time())
1210-
1250+
12111251
# Filter the DataFrame
12121252
if start_date is not None and end_date is not None:
12131253
df = df[(df.index >= start_datetime) & (df.index <= end_datetime)]
12141254
elif start_date is not None:
12151255
df = df[df.index >= start_datetime]
12161256
elif end_date is not None:
12171257
df = df[df.index <= end_datetime]
1218-
1258+
12191259
return df
1220-
1260+
12211261
except grpc.RpcError as e:
12221262
print(f"gRPC Error: {e.code().name}")
12231263
print(f"Details: {e.details()}")

0 commit comments

Comments
 (0)