from pathlib import Path
import re
path = Path("/content/AIQuant/aiquant/models/ensemble_pipeline.py")
text = path.read_text()
start = text.index("def _evaluate_threshold(")
# Ищем конец функции — следующую строку, начинающуюся не пробелом
m = re.search(r"\n(?=[^\s#].*)", text[start + 1:])
if not m:
raise RuntimeError("Не удалось определить конец функции")
end = start + 1 + m.start()
new_func = '''def _evaluate_threshold(lt, st, idx):
"""Evaluate thresholds only on the supplied validation/test indices."""
if idx is None or len(idx) == 0:
return None
idx = np.asarray(idx)
scores = ens_score[idx]
prices = c[idx]
sig = np.zeros(len(idx), dtype=np.int8)
sig[scores > lt] = 1
sig[scores < -st] = -1
changes = np.where(np.diff(sig, prepend=0) != 0)[0]
if len(changes) < 20:
return None
equity = np.full(len(idx), INITIAL_CAPITAL, dtype=np.float64)
position = 0
entry_price = 0.0
capital = INITIAL_CAPITAL
trade_pnls = []
for i in range(len(idx)):
price = prices[i]
new_position = int(sig[i])
if new_position != position:
if position != 0:
pnl = position * (price - entry_price) / entry_price
pnl -= FEE
capital *= (1.0 + pnl)
trade_pnls.append(pnl)
if new_position != 0:
capital *= (1.0 - FEE)
entry_price = price
position = new_position
equity[i] = capital
if position != 0:
pnl = position * (prices[-1] - entry_price) / entry_price
pnl -= FEE
capital *= (1.0 + pnl)
equity[-1] = capital
total_return = capital / INITIAL_CAPITAL - 1.0
returns = np.diff(equity) / np.maximum(equity[:-1], 1e-12)
if len(returns) > 1 and np.std(returns) > 0:
sharpe = np.mean(returns) / np.std(returns) * np.sqrt(1440 * 365)
else:
sharpe = 0.0
running_max = np.maximum.accumulate(equity)
drawdown = equity / np.maximum(running_max, 1e-12) - 1.0
max_dd = float(np.min(drawdown))
n_trades = len(trade_pnls)
if n_trades > 0:
wins = [x for x in trade_pnls if x > 0]
losses = [x for x in trade_pnls if x < 0]
win_rate = len(wins) / n_trades
gross_profit = sum(wins)
gross_loss = abs(sum(losses))
profit_factor = (
gross_profit / gross_loss
if gross_loss > 0
else np.inf
)
else:
win_rate = 0.0
profit_factor = 0.0
n_days = max(len(idx) / 1440.0, 1.0)
annual_return = (1.0 + total_return) ** (365.0 / n_days) - 1.0
calmar = (
annual_return / abs(max_dd)
if max_dd < 0
else 0.0
)
return {
"return": total_return,
"sharpe": sharpe,
"calmar": calmar,
"max_dd": max_dd,
"profit_factor": profit_factor,
"win_rate": win_rate,
"n_trades": n_trades,
"long_thresh": lt,
"short_thresh": st,
}
'''
text = text[:start] + new_func + text[end:]
path.write_text(text)
print("✅ _evaluate_threshold заменена")