Upload folder using huggingface_hub
Browse files- __pycache__/app.cpython-312.pyc +0 -0
- __pycache__/rebalance_engine.cpython-312.pyc +0 -0
- app.py +2 -1
- rebalance_engine.py +9 -3
__pycache__/app.cpython-312.pyc
CHANGED
|
Binary files a/__pycache__/app.cpython-312.pyc and b/__pycache__/app.cpython-312.pyc differ
|
|
|
__pycache__/rebalance_engine.cpython-312.pyc
CHANGED
|
Binary files a/__pycache__/rebalance_engine.cpython-312.pyc and b/__pycache__/rebalance_engine.cpython-312.pyc differ
|
|
|
app.py
CHANGED
|
@@ -176,7 +176,8 @@ def rebalance_preview():
|
|
| 176 |
acct = ac.get_account()
|
| 177 |
eq = float(acct["equity"])
|
| 178 |
positions = {p["symbol"]: float(p["market_value"]) for p in ac.get_positions()}
|
| 179 |
-
orders = eng.compute_orders(tgt["weights"], positions, eq
|
|
|
|
| 180 |
except Exception as e:
|
| 181 |
return f"### ⚠️ Could not build preview\n`{type(e).__name__}: {str(e)[:180]}`", pd.DataFrame(), pd.DataFrame()
|
| 182 |
reg = tgt["regime"]
|
|
|
|
| 176 |
acct = ac.get_account()
|
| 177 |
eq = float(acct["equity"])
|
| 178 |
positions = {p["symbol"]: float(p["market_value"]) for p in ac.get_positions()}
|
| 179 |
+
orders = eng.compute_orders(tgt["weights"], positions, eq,
|
| 180 |
+
force_sells=float(acct.get("cash", 0)) < 0)
|
| 181 |
except Exception as e:
|
| 182 |
return f"### ⚠️ Could not build preview\n`{type(e).__name__}: {str(e)[:180]}`", pd.DataFrame(), pd.DataFrame()
|
| 183 |
reg = tgt["regime"]
|
rebalance_engine.py
CHANGED
|
@@ -89,13 +89,17 @@ def get_target(token):
|
|
| 89 |
return {"regime": reg, "weights": weights, "rows": rows}
|
| 90 |
|
| 91 |
|
| 92 |
-
def compute_orders(weights, positions, equity, band_pct=0.005):
|
| 93 |
-
"""positions: {symbol: market_value $}. Returns order list (sells first), trading only the delta.
|
|
|
|
|
|
|
|
|
|
| 94 |
band = band_pct * equity
|
|
|
|
| 95 |
orders = []
|
| 96 |
for sym in set(weights) | set(positions):
|
| 97 |
tw = weights.get(sym, 0.0)
|
| 98 |
-
tgt = tw *
|
| 99 |
cur = positions.get(sym, 0.0)
|
| 100 |
delta = tgt - cur
|
| 101 |
cw = (cur / equity) if equity else 0.0
|
|
@@ -103,6 +107,8 @@ def compute_orders(weights, positions, equity, band_pct=0.005):
|
|
| 103 |
orders.append({"symbol": sym, "side": "SELL", "delta": -cur, "cur_w": cw, "tgt_w": 0.0, "exit": True})
|
| 104 |
elif cur == 0 and tgt > 1.0: # establish a new target position (always; band can't block it)
|
| 105 |
orders.append({"symbol": sym, "side": "BUY", "delta": tgt, "cur_w": 0.0, "tgt_w": tw, "exit": False})
|
|
|
|
|
|
|
| 106 |
elif abs(delta) < band: # churn guard: skip small adjustments to EXISTING positions
|
| 107 |
continue
|
| 108 |
else:
|
|
|
|
| 89 |
return {"regime": reg, "weights": weights, "rows": rows}
|
| 90 |
|
| 91 |
|
| 92 |
+
def compute_orders(weights, positions, equity, band_pct=0.005, invest_frac=0.995, force_sells=False):
|
| 93 |
+
"""positions: {symbol: market_value $}. Returns order list (sells first), trading only the delta.
|
| 94 |
+
invest_frac keeps a ~0.5% cash buffer so sell-proceeds slippage can't push cash negative (no margin).
|
| 95 |
+
force_sells (set when cash < 0): sell deltas bypass the band so a thin ~5% overshoot spread across
|
| 96 |
+
50 names can actually be trimmed back — otherwise every per-name trim is under the band."""
|
| 97 |
band = band_pct * equity
|
| 98 |
+
investable = equity * invest_frac
|
| 99 |
orders = []
|
| 100 |
for sym in set(weights) | set(positions):
|
| 101 |
tw = weights.get(sym, 0.0)
|
| 102 |
+
tgt = tw * investable
|
| 103 |
cur = positions.get(sym, 0.0)
|
| 104 |
delta = tgt - cur
|
| 105 |
cw = (cur / equity) if equity else 0.0
|
|
|
|
| 107 |
orders.append({"symbol": sym, "side": "SELL", "delta": -cur, "cur_w": cw, "tgt_w": 0.0, "exit": True})
|
| 108 |
elif cur == 0 and tgt > 1.0: # establish a new target position (always; band can't block it)
|
| 109 |
orders.append({"symbol": sym, "side": "BUY", "delta": tgt, "cur_w": 0.0, "tgt_w": tw, "exit": False})
|
| 110 |
+
elif force_sells and delta < -1.0: # de-leverage: trims bypass the band
|
| 111 |
+
orders.append({"symbol": sym, "side": "SELL", "delta": delta, "cur_w": cw, "tgt_w": tw, "exit": False})
|
| 112 |
elif abs(delta) < band: # churn guard: skip small adjustments to EXISTING positions
|
| 113 |
continue
|
| 114 |
else:
|