-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmarks.py
More file actions
96 lines (78 loc) · 3.05 KB
/
Copy pathbenchmarks.py
File metadata and controls
96 lines (78 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
from utis import get_amount
IBOVESPA_SYMBOL = "^BVSP"
USD_BRL_SYMBOL = "USDBRL=X"
def buy_and_hold_metrics(df, initial_balance):
"""Buy at first close in the fetched window; hold to last close."""
if df.empty:
return {
"buy_hold_total_value": initial_balance,
"buy_hold_gain_amount": 0.0,
"buy_hold_return_pct": 0.0,
"buy_hold_shares": 0,
"buy_hold_entry_price": 0.0,
"buy_hold_exit_price": 0.0,
}
entry_price = float(df["Close"].iloc[0])
exit_price = float(df["Close"].iloc[-1])
shares = get_amount(1.0, initial_balance, entry_price)
spent = shares * entry_price
total_value = shares * exit_price + (initial_balance - spent)
gain_amount = total_value - initial_balance
return_pct = (gain_amount / initial_balance) * 100 if initial_balance else 0
return {
"buy_hold_total_value": total_value,
"buy_hold_gain_amount": gain_amount,
"buy_hold_return_pct": return_pct,
"buy_hold_shares": shares,
"buy_hold_entry_price": entry_price,
"buy_hold_exit_price": exit_price,
}
def _indexed_series(df):
if df.empty:
return []
base = float(df["Close"].iloc[0])
return [
{"date": idx.isoformat(), "index": (float(row["Close"]) / base) * 100}
for idx, row in df.iterrows()
]
def period_return_metrics(df, initial_balance):
"""Percentage move over the window (for indices and FX rates)."""
if df.empty:
return {
"buy_hold_total_value": initial_balance,
"buy_hold_gain_amount": 0.0,
"buy_hold_return_pct": 0.0,
"buy_hold_shares": 0,
"buy_hold_entry_price": 0.0,
"buy_hold_exit_price": 0.0,
}
entry_price = float(df["Close"].iloc[0])
exit_price = float(df["Close"].iloc[-1])
return_pct = ((exit_price / entry_price) - 1) * 100 if entry_price else 0
gain_amount = initial_balance * (return_pct / 100)
total_value = initial_balance + gain_amount
return {
"buy_hold_total_value": total_value,
"buy_hold_gain_amount": gain_amount,
"buy_hold_return_pct": return_pct,
"buy_hold_shares": 0,
"buy_hold_entry_price": entry_price,
"buy_hold_exit_price": exit_price,
}
def _rate_benchmark(name, symbol, period, interval, initial_balance):
import yfinance as yf
df = yf.Ticker(symbol).history(period, interval)
metrics = period_return_metrics(df, initial_balance)
return {
"name": name,
"symbol": symbol,
"period": period,
"interval": interval,
**metrics,
"normalized_series": _indexed_series(df),
}
def ibovespa_benchmark(period, interval, initial_balance):
return _rate_benchmark("Ibovespa", IBOVESPA_SYMBOL, period, interval, initial_balance)
def dollar_benchmark(period, interval, initial_balance):
"""USD/BRL move over the period (BRL per USD; up = dollar strengthening)."""
return _rate_benchmark("USD/BRL", USD_BRL_SYMBOL, period, interval, initial_balance)