Spaces:
Runtime error
Runtime error
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import yfinance as yf
|
3 |
+
import numpy as np
|
4 |
+
import matplotlib.pyplot as plt
|
5 |
+
import seaborn as sns
|
6 |
+
from datetime import datetime
|
7 |
+
|
8 |
+
# Ensure visualization styles are set for the plots
|
9 |
+
sns.set(style="whitegrid")
|
10 |
+
plt.rcParams['figure.figsize'] = [10, 5]
|
11 |
+
|
12 |
+
def backtest_ema_strategy(asset_symbol, short_ema, long_ema, timeframe='1d'):
|
13 |
+
# Fetching financial data with dynamic timeframe and date range
|
14 |
+
start_date = '2020-01-01'
|
15 |
+
end_date = '2024-01-01'
|
16 |
+
asset_data = yf.download(asset_symbol, start=start_date, end=end_date, interval=timeframe)
|
17 |
+
|
18 |
+
# Check if data is empty (can happen with incorrect symbols or network issues)
|
19 |
+
if asset_data.empty:
|
20 |
+
return None, "Failed to fetch data. Please check the asset symbol and date range.", 0, 0
|
21 |
+
|
22 |
+
# Calculate the short-term and long-term EMAs
|
23 |
+
asset_data[f'EMA{short_ema}'] = asset_data['Close'].ewm(span=short_ema, adjust=False).mean()
|
24 |
+
asset_data[f'EMA{long_ema}'] = asset_data['Close'].ewm(span=long_ema, adjust=False).mean()
|
25 |
+
|
26 |
+
# Generate signals
|
27 |
+
asset_data['Signal'] = np.where(asset_data[f'EMA{short_ema}'] > asset_data[f'EMA{long_ema}'], 1, 0)
|
28 |
+
asset_data['Position'] = asset_data['Signal'].diff()
|
29 |
+
|
30 |
+
# Plotting
|
31 |
+
plt.figure(figsize=(14, 7))
|
32 |
+
plt.plot(asset_data['Close'], label=f'{asset_symbol} Close', alpha=0.5)
|
33 |
+
plt.plot(asset_data[f'EMA{short_ema}'], label=f'{short_ema}-day EMA', alpha=0.75)
|
34 |
+
plt.plot(asset_data[f'EMA{long_ema}'], label=f'{long_ema}-day EMA', alpha=0.75)
|
35 |
+
plt.plot(asset_data[asset_data['Position'] == 1].index, asset_data[f'EMA{short_ema}'][asset_data['Position'] == 1], '^', markersize=10, color='g', lw=0, label='Buy Signal')
|
36 |
+
plt.plot(asset_data[asset_data['Position'] == -1].index, asset_data[f'EMA{short_ema}'][asset_data['Position'] == -1], 'v', markersize=10, color='r', lw=0, label='Sell Signal')
|
37 |
+
plt.title(f'{asset_symbol} EMA Crossover Trading Strategy')
|
38 |
+
plt.legend()
|
39 |
+
plt_path = f"{asset_symbol}_EMA_Strategy.png"
|
40 |
+
plt.savefig(plt_path)
|
41 |
+
plt.close()
|
42 |
+
|
43 |
+
# Calculating total and annual returns
|
44 |
+
initial_price = asset_data['Close'].iloc[0]
|
45 |
+
final_price = asset_data['Close'].iloc[-1]
|
46 |
+
total_returns = ((final_price - initial_price) / initial_price) * 100
|
47 |
+
years_diff = (datetime.strptime(end_date, "%Y-%m-%d") - datetime.strptime(start_date, "%Y-%m-%d")).days / 365.25
|
48 |
+
annual_returns = ((final_price / initial_price) ** (1 / years_diff) - 1) * 100
|
49 |
+
|
50 |
+
# Returning path of the saved plot, total and annual returns
|
51 |
+
return plt_path, "Backtest completed message", total_returns, annual_returns
|
52 |
+
|
53 |
+
|
54 |
+
def create_gradio_interface(asset_symbol, short_ema, long_ema, timeframe):
|
55 |
+
# Convert string inputs for EMAs to integers and pass all new parameters to the backtest strategy
|
56 |
+
short_ema = int(short_ema)
|
57 |
+
long_ema = int(long_ema)
|
58 |
+
|
59 |
+
plot_path, message,total_returns, annual_returns = backtest_ema_strategy(asset_symbol, short_ema, long_ema, timeframe)
|
60 |
+
|
61 |
+
# Prepare and return the results
|
62 |
+
result_text = [
|
63 |
+
[message], # f"Backtest completed for {asset_symbol} from {start_date} to {end_date} using {timeframe} data.",
|
64 |
+
[f"Total Returns: {total_returns:.2f}%"],
|
65 |
+
[f"Annual Returns: {annual_returns:.2f}%"]
|
66 |
+
]
|
67 |
+
|
68 |
+
return plot_path, result_text
|
69 |
+
|
70 |
+
|
71 |
+
# Expanded list of major assets to include Indian indices and major stocks
|
72 |
+
major_assets = [
|
73 |
+
# Global and Cryptocurrencies
|
74 |
+
"AAPL", # Apple
|
75 |
+
"GOOGL", # Alphabet
|
76 |
+
"MSFT", # Microsoft
|
77 |
+
"AMZN", # Amazon
|
78 |
+
"FB", # Facebook
|
79 |
+
"TSLA", # Tesla
|
80 |
+
"BTC-USD", # Bitcoin
|
81 |
+
"ETH-USD", # Ethereum
|
82 |
+
# # Indian Indices and Major Stocks
|
83 |
+
# "NIFTY50.NS", # Nifty 50 Index
|
84 |
+
# "RELIANCE.NS", # Reliance Industries Limited
|
85 |
+
# "TCS.NS", # Tata Consultancy Services
|
86 |
+
# "HDFCBANK.NS", # HDFC Bank
|
87 |
+
# "INFY.NS", # Infosys
|
88 |
+
# "HINDUNILVR.NS", # Hindustan Unilever
|
89 |
+
# "ITC.NS", # ITC Limited
|
90 |
+
# "SBIN.NS", # State Bank of India
|
91 |
+
# "ICICIBANK.NS", # ICICI Bank
|
92 |
+
# "BHARTIARTL.NS", # Bharti Airtel
|
93 |
+
]
|
94 |
+
|
95 |
+
# Define the Gradio app with updated inputs
|
96 |
+
iface = gr.Interface(
|
97 |
+
fn=create_gradio_interface,
|
98 |
+
inputs=[
|
99 |
+
gr.Dropdown(choices=major_assets, label="Asset Symbol (Select or type, e.g., NIFTY50.NS)"),
|
100 |
+
gr.Textbox(label="Short EMA Period"),
|
101 |
+
gr.Textbox(label="Long EMA Period"),
|
102 |
+
gr.Dropdown(choices=['1d', '1wk', '1mo'], label="Timeframe (1d = daily, 1wk = weekly, 1mo = monthly)"),
|
103 |
+
|
104 |
+
],
|
105 |
+
outputs=[
|
106 |
+
gr.Image(label="Trading Strategy Chart"),
|
107 |
+
gr.List(label="Results")
|
108 |
+
],
|
109 |
+
title="EMA Crossover Trading Strategy Backtest",
|
110 |
+
description="Enter the asset symbol, EMA periods, timeframe, and date range to backtest the EMA Crossover Trading Strategy."
|
111 |
+
)
|
112 |
+
|
113 |
+
|
114 |
+
|
115 |
+
# Launch the app
|
116 |
+
if __name__ == "__main__":
|
117 |
+
iface.launch(share=True)
|