Tulitula commited on
Commit
064bf5c
·
verified ·
1 Parent(s): 46d1fe1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -8
app.py CHANGED
@@ -370,7 +370,7 @@ def suggest_one_per_band(synth: pd.DataFrame, sigma_mkt: float, universe_user: L
370
  out[band.lower()] = chosen
371
  return out
372
 
373
- # -------------- UI helpers --------------
374
  def empty_positions_df():
375
  return pd.DataFrame(columns=["ticker", "amount_usd", "weight_exposure", "beta"])
376
 
@@ -386,6 +386,47 @@ def set_horizon(years: float):
386
  RF_CODE = code
387
  RF_ANN = rf
388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  # -------------- main compute --------------
390
  UNIVERSE: List[str] = [MARKET_TICKER, "QQQ", "VTI", "SOXX", "IBIT"]
391
 
@@ -417,13 +458,10 @@ def compute(
417
 
418
  symbols = [t for t in df["ticker"].tolist() if t]
419
  if len(symbols) == 0:
420
- # hide suggestions
421
  hide = gr.update(visible=False)
422
  return (
423
  None, "Add at least one ticker.", empty_positions_df(), empty_suggestion_df(), None,
424
- gr.update(visible=False), # sugg header
425
- gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), # low/med/high text
426
- gr.update(visible=False), gr.update(visible=False), gr.update(visible=False) # buttons
427
  )
428
 
429
  symbols = validate_tickers(symbols, years_lookback)
@@ -462,7 +500,7 @@ def compute(
462
  a_sigma, b_sigma, mu_eff_same_sigma = efficient_same_sigma(sigma_hist, rf_ann, erp_ann, sigma_mkt)
463
  a_mu, b_mu, sigma_eff_same_mu = efficient_same_return(mu_capm, rf_ann, erp_ann, sigma_mkt)
464
 
465
- # Synthetic dataset & suggestions — exactly the user's tickers
466
  user_universe = list(symbols)
467
  synth = build_synthetic_dataset(user_universe, covA, betas, rf_ann, erp_ann, sigma_mkt, n_rows=SYNTH_ROWS)
468
  csv_path = os.path.join(DATA_DIR, f"investor_profiles_{int(time.time())}.csv")
@@ -510,7 +548,6 @@ def compute(
510
  sugg_sigma_hist=chosen_sigma, sugg_mu_capm=chosen_mu
511
  )
512
 
513
- # summary text
514
  info = "\n".join([
515
  "### Inputs",
516
  f"- Lookback years {years_lookback}",
@@ -531,7 +568,6 @@ def compute(
531
  "Weights may exceed 1 (leverage) or be negative (borrowing). If leverage isn’t allowed, scale toward 1.0."
532
  ])
533
 
534
- # show Suggestions section now
535
  show = gr.update(visible=True)
536
  return (
537
  img, info, pos_table, sugg_table, csv_path,
 
370
  out[band.lower()] = chosen
371
  return out
372
 
373
+ # -------------- UI helpers (restored) --------------
374
  def empty_positions_df():
375
  return pd.DataFrame(columns=["ticker", "amount_usd", "weight_exposure", "beta"])
376
 
 
386
  RF_CODE = code
387
  RF_ANN = rf
388
 
389
+ def search_tickers_cb(q: str):
390
+ opts = yahoo_search(q)
391
+ note = "Select a symbol and click 'Add selected to portfolio'." if opts else "No matches."
392
+ return note, gr.update(choices=opts, value=None)
393
+
394
+ def add_symbol(selection: str, table: Optional[pd.DataFrame]):
395
+ if not selection:
396
+ return table if isinstance(table, pd.DataFrame) else pd.DataFrame(columns=["ticker","amount_usd"]), "Pick a row in Matches first."
397
+ symbol = selection.split("|")[0].strip().upper()
398
+
399
+ current = []
400
+ if isinstance(table, pd.DataFrame) and not table.empty:
401
+ current = [str(x).upper() for x in table["ticker"].tolist() if str(x) != "nan"]
402
+ tickers = current if symbol in current else current + [symbol]
403
+
404
+ val = validate_tickers(tickers, years=DEFAULT_LOOKBACK_YEARS)
405
+ tickers = [t for t in tickers if t in val]
406
+
407
+ amt_map = {}
408
+ if isinstance(table, pd.DataFrame) and not table.empty:
409
+ for _, r in table.iterrows():
410
+ t = str(r.get("ticker", "")).upper()
411
+ if t in tickers:
412
+ amt_map[t] = float(pd.to_numeric(r.get("amount_usd", 0.0), errors="coerce") or 0.0)
413
+
414
+ new_table = pd.DataFrame({"ticker": tickers, "amount_usd": [amt_map.get(t, 0.0) for t in tickers]})
415
+ if len(new_table) > MAX_TICKERS:
416
+ new_table = new_table.iloc[:MAX_TICKERS]
417
+ return new_table, f"Reached max of {MAX_TICKERS}."
418
+ return new_table, f"Added {symbol}."
419
+
420
+ def lock_ticker_column(tb: Optional[pd.DataFrame]):
421
+ if not isinstance(tb, pd.DataFrame) or tb.empty:
422
+ return pd.DataFrame(columns=["ticker", "amount_usd"])
423
+ tickers = [str(x).upper() for x in tb["ticker"].tolist()]
424
+ amounts = pd.to_numeric(tb["amount_usd"], errors="coerce").fillna(0.0).tolist()
425
+ val = validate_tickers(tickers, years=DEFAULT_LOOKBACK_YEARS)
426
+ tickers = [t for t in tickers if t in val]
427
+ amounts = amounts[:len(tickers)] + [0.0] * max(0, len(tickers) - len(amounts))
428
+ return pd.DataFrame({"ticker": tickers, "amount_usd": amounts})
429
+
430
  # -------------- main compute --------------
431
  UNIVERSE: List[str] = [MARKET_TICKER, "QQQ", "VTI", "SOXX", "IBIT"]
432
 
 
458
 
459
  symbols = [t for t in df["ticker"].tolist() if t]
460
  if len(symbols) == 0:
 
461
  hide = gr.update(visible=False)
462
  return (
463
  None, "Add at least one ticker.", empty_positions_df(), empty_suggestion_df(), None,
464
+ hide, hide, hide, hide, hide, hide, hide
 
 
465
  )
466
 
467
  symbols = validate_tickers(symbols, years_lookback)
 
500
  a_sigma, b_sigma, mu_eff_same_sigma = efficient_same_sigma(sigma_hist, rf_ann, erp_ann, sigma_mkt)
501
  a_mu, b_mu, sigma_eff_same_mu = efficient_same_return(mu_capm, rf_ann, erp_ann, sigma_mkt)
502
 
503
+ # Synthetic dataset & suggestions
504
  user_universe = list(symbols)
505
  synth = build_synthetic_dataset(user_universe, covA, betas, rf_ann, erp_ann, sigma_mkt, n_rows=SYNTH_ROWS)
506
  csv_path = os.path.join(DATA_DIR, f"investor_profiles_{int(time.time())}.csv")
 
548
  sugg_sigma_hist=chosen_sigma, sugg_mu_capm=chosen_mu
549
  )
550
 
 
551
  info = "\n".join([
552
  "### Inputs",
553
  f"- Lookback years {years_lookback}",
 
568
  "Weights may exceed 1 (leverage) or be negative (borrowing). If leverage isn’t allowed, scale toward 1.0."
569
  ])
570
 
 
571
  show = gr.update(visible=True)
572
  return (
573
  img, info, pos_table, sugg_table, csv_path,