Archivo: goldv2.
py Página 1 de 3
1 import yfinance as yf
2 import pandas as pd
3 import numpy as np
4 import [Link] as plt
5 import pandas_ta as ta # Cambio 1: Reemplazar talib
6 from pmdarima import auto_arima
7 from [Link] import RandomForestRegressor
8 from sklearn.model_selection import train_test_split
9 import vectorbt as vbt
10 import streamlit as st
11
12 st.set_page_config(page_title="Estrategia Mejorada para Oro",
layout="wide")
13
14 # 1. Descarga de datos y datos externos (igual)
15 @st.cache_data
16 def get_data(start_date="2010-01-01",
end_date=[Link]().strftime("%Y-%m-%d")):
17 gold = [Link]("GC=F", start=start_date, end=end_date)
18 dxy = [Link]("[Link]", start=start_date, end=end_date)
['Close'].rename('DXY')
19 data = [Link](gold, dxy, left_index=True, right_index=True,
how='left')
20 data['DXY'].ffill(inplace=True)
21 gld = [Link]("GLD", start=start_date, end=end_date)
['Volume'].rename('GLD_Vol')
22 data = [Link](data, gld, left_index=True, right_index=True,
how='left')
23 [Link](inplace=True)
24 return data
25
26 # 2. Indicadores técnicos con pandas_ta
27 def add_indicators(df):
28 df = [Link]()
29
30 # Cambio 2: Modificar todas las funciones de talib
31 df['RSI'] = [Link](df['Close'], length=14) # length en lugar de
timeperiod
32 df['ATR'] = [Link](df['High'], df['Low'], df['Close'], length=14)
33
34 # MACD devuelve un DataFrame con 3 columnas
35 macd = [Link](df['Close'], fast=12, slow=26, signal=9)
36 df['MACD'] = macd['MACD_12_26_9']
37 df['MACD_Signal'] = macd['MACDs_12_26_9']
38
39 df['SMA50'] = [Link](df['Close'], length=50)
40 df['SMA200'] = [Link](df['Close'], length=200)
41
42 # Bollinger Bands
43 bb = [Link](df['Close'], length=20)
44 df['Upper_BB'] = bb['BBU_20_2.0']
45 df['Middle_BB'] = bb['BBM_20_2.0']
46 df['Lower_BB'] = bb['BBL_20_2.0']
47
48 # El resto del código se mantiene igual
49 df['Volume_MA20'] = df['Volume'].rolling(20).mean()
50 df['Volume_Ratio'] = df['Volume'] / df['Volume_MA20']
51 df['Return'] = df['Close'].pct_change()
52 df['Volatility'] = df['Close'].rolling(30).std()
Archivo: [Link] Página 2 de 3
53 df['Gold_DXY_Ratio'] = df['Close'] / df['DXY']
54 df['GLD_Vol_MA10'] = df['GLD_Vol'].rolling(10).mean()
55
56 [Link](inplace=True)
57 return df
58
59 # 3. Modelo predictivo (igual)
60 def add_predictions(df):
61 features = ['RSI', 'ATR', 'MACD', 'SMA50', 'SMA200',
62 'Volume_Ratio', 'DXY', 'Gold_DXY_Ratio', 'Volatility']
63
64 X = df[features]
65 y = df['Return'].shift(-1).fillna(0)
66
67 X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2, shuffle=False)
68
69 model = RandomForestRegressor(n_estimators=100, random_state=42)
70 [Link](X_train, y_train)
71
72 df['Predicted_Return'] = [Link](X)
73 df['Model_Signal'] = [Link](df['Predicted_Return'] > 0.005, 1,
74 [Link](df['Predicted_Return'] < -0.005,
-1, 0))
75 return df
76
77 # 4. Generación de señales (corregir paréntesis faltantes)
78 def generate_signals(df):
79 # Cambio 3: Corregir paréntesis faltantes
80 buy_conditions = (
81 (df['RSI'] < 35) &
82 (df['Close'] > df['SMA200']) &
83 (df['MACD'] > df['MACD_Signal']) &
84 (df['Volume_Ratio'] > 1.2) &
85 (df['Model_Signal'] == 1)
86 ) # <-- Añadir este paréntesis
87
88 sell_conditions = (
89 (df['RSI'] > 65) &
90 (df['Close'] < df['SMA50']) &
91 (df['MACD'] < df['MACD_Signal']) &
92 (df['Volume_Ratio'] > 1.2) &
93 (df['Model_Signal'] == -1)
94 ) # <-- Añadir este paréntesis
95
96 df['Buy_Signal'] = buy_conditions.astype(int)
97 df['Sell_Signal'] = sell_conditions.astype(int)
98
99 return df
100
101 # 5. Gestión de riesgo dinámica (igual)
102 def risk_management(df):
103 df['ATR_Rolling'] = df['ATR'].rolling(30).mean()
104 df['Stop_Mult'] = 2 * (df['ATR'] / df['ATR_Rolling'])
105 df['TP_Mult'] = 3 * (df['ATR'] / df['ATR_Rolling'])
106
107 def arima_forecast(series):
108 try:
109 model = auto_arima(series, seasonal=False, trace=False)
Archivo: [Link] Página 3 de 3
110 return [Link](n_periods=3)[-1]
111 except:
112 return [Link]
113
114 df['ARIMA_Forecast'] = df['Close'].rolling(100).apply(arima_forecast,
raw=False)
115
116 return df
117
118 # --- Ejecución principal ---
119 data = get_data()
120 data = add_indicators(data)
121 data = add_predictions(data)
122 data = generate_signals(data)
123 data = risk_management(data)
124
125 # 6. Backtesting con VectorBT
126 entries = data['Buy_Signal']
127 exits = data['Sell_Signal']
128
129 pf = [Link].from_orders(
130 close=data['Close'],
131 entries=entries,
132 exits=exits,
133 fees=0.001, # 0.1% por trade
134 freq='D'
135 )
136
137 # 7. Visualización en Streamlit
138 [Link]("Estrategia Cuantitativa Mejorada para Oro")
139
140 # Métricas de performance
141 returns = pf.total_return()
142 sharpe = pf.sharpe_ratio()
143 max_dd = pf.max_drawdown()
144
145 col1, col2, col3 = [Link](3)
146 [Link]("Retorno Total", f"{returns*100:.2f}%")
147 [Link]("Ratio de Sharpe", f"{sharpe:.2f}")
148 [Link]("Máximo Drawdown", f"{max_dd*100:.2f}%")
149
150 # Gráficos
151 fig1 = [Link](subplots=['orders', 'trade_pnl', 'drawdowns'])
152 [Link](fig1)
153
154 fig2, ax = [Link](figsize=(12,6))
155 data['Close'].plot(ax=ax, label='Precio')
156 data[[Link](bool)]['Close'].plot(ax=ax, style='^', markersize=10,
color='g', label='Compra')
157 data[[Link](bool)]['Close'].plot(ax=ax, style='v', markersize=10,
color='r', label='Venta')
158 ax.set_title("Señales de Trading")
159 [Link]()
160 [Link](fig2)
161
162 # Dataframe con señales
163 [Link]("Últimas 20 Señales")
164 [Link](data[['Close', 'RSI', 'MACD', 'SMA50', 'SMA200',
'Buy_Signal', 'Sell_Signal']].tail(20))