Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -312,6 +312,53 @@ def build_custom_index(symbols_df: pd.DataFrame, index_type: str, exchange: str)
|
|
| 312 |
|
| 313 |
return {"index_value": round(index_value, 2), "components": prices, "weights": weights}
|
| 314 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
# ========== Comparison UI functions ==========
|
| 316 |
def create_comparison_ui():
|
| 317 |
"""Return UI components for index comparison tab."""
|
|
@@ -361,7 +408,6 @@ with gr.Blocks(title="AI-Powered Index Analyst with Real-Time Data") as demo:
|
|
| 361 |
""")
|
| 362 |
|
| 363 |
with gr.Tab("π¬ Conversational Assistant"):
|
| 364 |
-
# Remove type="messages" β use classic list-of-lists format
|
| 365 |
chat_history = gr.Chatbot(label="Conversation", height=400)
|
| 366 |
msg = gr.Textbox(
|
| 367 |
label="Ask about stocks or indices",
|
|
@@ -469,11 +515,39 @@ with gr.Blocks(title="AI-Powered Index Analyst with Real-Time Data") as demo:
|
|
| 469 |
)
|
| 470 |
|
| 471 |
with gr.Tab("π Index Calculator"):
|
| 472 |
-
# Simplified placeholder β you can expand with actual calculations later
|
| 473 |
gr.Markdown("""
|
| 474 |
-
### Index Calculator
|
| 475 |
-
|
|
|
|
| 476 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 477 |
|
| 478 |
with gr.Tab("π Index Comparison"):
|
| 479 |
comp_ui = create_comparison_ui()
|
|
|
|
| 312 |
|
| 313 |
return {"index_value": round(index_value, 2), "components": prices, "weights": weights}
|
| 314 |
|
| 315 |
+
# ========== Index Calculator functions ==========
|
| 316 |
+
def calculate_indices(df: pd.DataFrame):
|
| 317 |
+
"""
|
| 318 |
+
Compute Laspeyres, Paasche, and Fisher indices from input dataframe.
|
| 319 |
+
Expected columns: Item, p0, q0, p1, q1
|
| 320 |
+
"""
|
| 321 |
+
if df.empty:
|
| 322 |
+
return "Please enter data.", 0, 0, 0, go.Figure()
|
| 323 |
+
|
| 324 |
+
# Convert to numeric, handle errors
|
| 325 |
+
try:
|
| 326 |
+
df['p0'] = pd.to_numeric(df['p0'], errors='coerce')
|
| 327 |
+
df['q0'] = pd.to_numeric(df['q0'], errors='coerce')
|
| 328 |
+
df['p1'] = pd.to_numeric(df['p1'], errors='coerce')
|
| 329 |
+
df['q1'] = pd.to_numeric(df['q1'], errors='coerce')
|
| 330 |
+
except Exception as e:
|
| 331 |
+
return f"Error converting data: {e}", 0, 0, 0, go.Figure()
|
| 332 |
+
|
| 333 |
+
# Drop rows with NaN
|
| 334 |
+
df = df.dropna()
|
| 335 |
+
if df.empty:
|
| 336 |
+
return "No valid numeric data.", 0, 0, 0, go.Figure()
|
| 337 |
+
|
| 338 |
+
# Calculate sums
|
| 339 |
+
sum_p0q0 = (df['p0'] * df['q0']).sum()
|
| 340 |
+
sum_p1q0 = (df['p1'] * df['q0']).sum()
|
| 341 |
+
sum_p0q1 = (df['p0'] * df['q1']).sum()
|
| 342 |
+
sum_p1q1 = (df['p1'] * df['q1']).sum()
|
| 343 |
+
|
| 344 |
+
# Avoid division by zero
|
| 345 |
+
if sum_p0q0 == 0 or sum_p0q1 == 0:
|
| 346 |
+
return "Base period expenditure is zero, cannot compute indices.", 0, 0, 0, go.Figure()
|
| 347 |
+
|
| 348 |
+
laspeyres = (sum_p1q0 / sum_p0q0) * 100
|
| 349 |
+
paasche = (sum_p1q1 / sum_p0q1) * 100
|
| 350 |
+
fisher = np.sqrt(laspeyres * paasche)
|
| 351 |
+
|
| 352 |
+
# Create comparison chart
|
| 353 |
+
fig = go.Figure(data=[
|
| 354 |
+
go.Bar(name='Index Value', x=['Laspeyres', 'Paasche', 'Fisher'],
|
| 355 |
+
y=[laspeyres, paasche, fisher])
|
| 356 |
+
])
|
| 357 |
+
fig.update_layout(title="Price Index Comparison", yaxis_title="Index Value")
|
| 358 |
+
|
| 359 |
+
result_text = f"**Laspeyres Index:** {laspeyres:.2f}\n**Paasche Index:** {paasche:.2f}\n**Fisher Index:** {fisher:.2f}"
|
| 360 |
+
return result_text, laspeyres, paasche, fisher, fig
|
| 361 |
+
|
| 362 |
# ========== Comparison UI functions ==========
|
| 363 |
def create_comparison_ui():
|
| 364 |
"""Return UI components for index comparison tab."""
|
|
|
|
| 408 |
""")
|
| 409 |
|
| 410 |
with gr.Tab("π¬ Conversational Assistant"):
|
|
|
|
| 411 |
chat_history = gr.Chatbot(label="Conversation", height=400)
|
| 412 |
msg = gr.Textbox(
|
| 413 |
label="Ask about stocks or indices",
|
|
|
|
| 515 |
)
|
| 516 |
|
| 517 |
with gr.Tab("π Index Calculator"):
|
|
|
|
| 518 |
gr.Markdown("""
|
| 519 |
+
### Price Index Calculator
|
| 520 |
+
Enter items with base period prices (p0) and quantities (q0), and current period prices (p1) and quantities (q1).
|
| 521 |
+
The calculator will compute Laspeyres, Paasche, and Fisher indices.
|
| 522 |
""")
|
| 523 |
+
|
| 524 |
+
index_df = gr.Dataframe(
|
| 525 |
+
headers=["Item", "p0", "q0", "p1", "q1"],
|
| 526 |
+
datatype=["str", "number", "number", "number", "number"],
|
| 527 |
+
row_count=5,
|
| 528 |
+
col_count=5,
|
| 529 |
+
value=[["Item1", 10, 100, 12, 110],
|
| 530 |
+
["Item2", 20, 50, 22, 55],
|
| 531 |
+
["Item3", 30, 30, 33, 32],
|
| 532 |
+
["Item4", 40, 20, 44, 18],
|
| 533 |
+
["Item5", 50, 10, 55, 9]]
|
| 534 |
+
)
|
| 535 |
+
|
| 536 |
+
calc_index_btn = gr.Button("Calculate Indices", variant="primary")
|
| 537 |
+
|
| 538 |
+
with gr.Row():
|
| 539 |
+
laspeyres_out = gr.Number(label="Laspeyres Index")
|
| 540 |
+
paasche_out = gr.Number(label="Paasche Index")
|
| 541 |
+
fisher_out = gr.Number(label="Fisher Index")
|
| 542 |
+
|
| 543 |
+
index_results = gr.Textbox(label="Detailed Results", lines=4)
|
| 544 |
+
index_plot = gr.Plot(label="Index Comparison Chart")
|
| 545 |
+
|
| 546 |
+
calc_index_btn.click(
|
| 547 |
+
calculate_indices,
|
| 548 |
+
inputs=[index_df],
|
| 549 |
+
outputs=[index_results, laspeyres_out, paasche_out, fisher_out, index_plot]
|
| 550 |
+
)
|
| 551 |
|
| 552 |
with gr.Tab("π Index Comparison"):
|
| 553 |
comp_ui = create_comparison_ui()
|