tosin2013 commited on
Commit
5d8b198
1 Parent(s): 9805f49

updating code

Browse files
Files changed (2) hide show
  1. app.py +256 -2
  2. requirements.txt +4 -1
app.py CHANGED
@@ -1,7 +1,261 @@
1
  import gradio as gr
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  iface = gr.Interface(fn=greet, inputs="text", outputs="text")
7
  iface.launch()
 
1
  import gradio as gr
2
+ import pandas as pd
3
+ import backtrader as bt
4
+ import requests
5
 
6
+ class TrendFollowingStrategy(bt.Strategy):
7
+ params = (('ma_period', 15),)
8
+
9
+ def __init__(self):
10
+ self.ma = bt.indicators.SimpleMovingAverage(self.data.close, period=self.params.ma_period)
11
+ self.crossover = bt.ind.CrossOver(self.data.close, self.ma)
12
+ self.last_signal = None
13
+ self.last_signal_timeframe = self.data._timeframe
14
+
15
+ # Additional tracking
16
+ self.trade_count = 0
17
+ self.win_count = 0
18
+ self.loss_count = 0
19
+
20
+ def next(self):
21
+ # Check if we are in the market
22
+ if not self.position:
23
+ # We are not in the market, look for a signal to enter
24
+ if self.crossover > 0:
25
+ self.buy() # Execute a buy order
26
+ self.last_signal = 'CALL'
27
+ elif self.crossover < 0:
28
+ self.sell() # Execute a sell order
29
+ self.last_signal = 'PUT'
30
+ else:
31
+ # We are in the market, look for a signal to close
32
+ if self.position.size > 0 and self.crossover < 0:
33
+ # We are long and get a sell signal
34
+ self.close() # Close the long position
35
+ elif self.position.size < 0 and self.crossover > 0:
36
+ # We are short and get a buy signal
37
+ self.close() # Close the short position
38
+
39
+
40
+ def notify_trade(self, trade):
41
+ if trade.isclosed:
42
+ outcome = 'win' if trade.pnl > 0 else 'loss'
43
+ self.log_trade(self.last_signal, outcome)
44
+
45
+ def log_trade(self, trade_type, outcome):
46
+ """
47
+ Log the details of each trade.
48
+ """
49
+ self.trade_count += 1
50
+ if outcome == 'win':
51
+ self.win_count += 1
52
+ elif outcome == 'loss':
53
+ self.loss_count += 1
54
+ print(f"Trade {self.trade_count}: {trade_type} - {outcome}")
55
+
56
+ def fetch_forex_intraday(api_key, from_symbol, to_symbol, interval, outputsize='compact'):
57
+ url = f'https://www.alphavantage.co/query?function=FX_INTRADAY&from_symbol={from_symbol}&to_symbol={to_symbol}&interval={interval}&apikey={api_key}&outputsize={outputsize}'
58
+ response = requests.get(url)
59
+ data = response.json()
60
+
61
+ # Extracting the time series data from the JSON object
62
+ time_series_key = 'Time Series FX (' + interval + ')'
63
+ forex_data = pd.DataFrame(data[time_series_key]).T
64
+ forex_data.columns = ['Open', 'High', 'Low', 'Close']
65
+
66
+ # Convert index to datetime and sort data
67
+ forex_data.index = pd.to_datetime(forex_data.index)
68
+ forex_data.sort_index(inplace=True)
69
+
70
+ # Convert columns to numeric
71
+ forex_data = forex_data.apply(pd.to_numeric)
72
+
73
+ return forex_data
74
+
75
+ def analyze_sentiment(json_response, target_ticker):
76
+ """
77
+ Analyze the sentiment data for a specific ticker.
78
+
79
+ :param json_response: The JSON response from the API.
80
+ :param target_ticker: The ticker symbol to analyze (e.g., base_ticker).
81
+ :return: A string describing the overall sentiment for the target ticker.
82
+ """
83
+ if not json_response or "feed" not in json_response:
84
+ return "No data available for analysis"
85
+
86
+ sentiment_label = "Neutral" # Default sentiment
87
+ highest_relevance = 0 # Track the highest relevance score
88
+
89
+ # Loop through each news item in the feed
90
+ for item in json_response.get("feed", []):
91
+ # Check each ticker sentiment in the item
92
+ for ticker_data in item.get("ticker_sentiment", []):
93
+ if ticker_data["ticker"] == target_ticker:
94
+ relevance_score = float(ticker_data.get("relevance_score", 0))
95
+ sentiment_score = float(ticker_data.get("ticker_sentiment_score", 0))
96
+
97
+ # Determine the sentiment label based on the score
98
+ if relevance_score > highest_relevance:
99
+ highest_relevance = relevance_score
100
+ if sentiment_score <= -0.35:
101
+ sentiment_label = "Bearish"
102
+ elif -0.35 < sentiment_score <= -0.15:
103
+ sentiment_label = "Somewhat-Bearish"
104
+ elif -0.15 < sentiment_score < 0.15:
105
+ sentiment_label = "Neutral"
106
+ elif 0.15 <= sentiment_score < 0.35:
107
+ sentiment_label = "Somewhat_Bullish"
108
+ elif sentiment_score >= 0.35:
109
+ sentiment_label = "Bullish"
110
+
111
+ return sentiment_label
112
+
113
+ def make_trade_decision(base_currency, quote_currency, quote_sentiment, base_sentiment):
114
+ """
115
+ Make a trade decision based on sentiment analysis and forex signal parameters.
116
+
117
+ :param quote_sentiment: Sentiment analysis result for {base_currency}.
118
+ :param base_sentiment: Sentiment analysis result for {quote_currency}.
119
+ :param entry: Entry price for the trade.
120
+ :param stop_loss: Stop loss price.
121
+ :param take_profit: Take profit price.
122
+ :return: A decision to make the trade or not, along with sentiment analysis results.
123
+ """
124
+ trade_decision = "No trade"
125
+ decision_reason = f"{base_currency} Sentiment: {quote_sentiment}, {quote_currency} Sentiment: {base_sentiment}"
126
+
127
+ # Adjust the logic to account for somewhat bullish/bearish sentiments
128
+ bullish_sentiments = ["Bullish", "Somewhat_Bullish"]
129
+ bearish_sentiments = ["Bearish", "Somewhat-Bearish"]
130
+
131
+ if quote_sentiment in bullish_sentiments and base_sentiment not in bullish_sentiments:
132
+ trade_decision = f"Sell {base_currency}/{quote_currency}"
133
+ elif base_sentiment in bullish_sentiments and quote_sentiment not in bullish_sentiments:
134
+ trade_decision = f"Buy {base_currency}/{quote_currency}"
135
+ elif quote_sentiment in bearish_sentiments and base_sentiment not in bearish_sentiments:
136
+ trade_decision = f"Buy {base_currency}/{quote_currency}"
137
+ elif base_sentiment in bearish_sentiments and quote_sentiment not in bearish_sentiments:
138
+ trade_decision = f"Sell {base_currency}/{quote_currency}"
139
+
140
+
141
+ return trade_decision, decision_reason
142
+
143
+ def fetch_sentiment_data(api_endpoint, ticker, api_key, sort='LATEST', limit=50):
144
+ # Prepare the query parameters
145
+ params = {
146
+ 'function': 'NEWS_SENTIMENT',
147
+ 'tickers': ticker,
148
+ 'apikey': api_key,
149
+ 'sort': sort,
150
+ 'limit': limit
151
+ }
152
+
153
+ # Make the API request
154
+ response = requests.get(api_endpoint, params=params)
155
+
156
+ # Check if the request was successful
157
+ if response.status_code == 200:
158
+ # Return the JSON response
159
+ return response.json()
160
+ else:
161
+ # Return an error message
162
+ return f"Error fetching data: {response.status_code}"
163
+
164
+ def load_data(api_key, from_symbol, to_symbol, interval):
165
+ # Fetch data using the Alpha Vantage API
166
+ forex_data = fetch_forex_intraday(api_key, from_symbol, to_symbol, interval)
167
+
168
+ # Convert the pandas dataframe to a Backtrader data feed
169
+ data = bt.feeds.PandasData(dataname=forex_data)
170
+ return data
171
+
172
+ def should_trade(strategy, api_endpoint, api_key, base_currency, quote_currency):
173
+ consistent_periods = 3
174
+ if len(strategy) < consistent_periods:
175
+ return False, None, None, "Insufficient data"
176
+
177
+ if strategy.last_signal_timeframe in bt.TimeFrame.Names:
178
+ timeframe = bt.TimeFrame.getname(strategy.last_signal_timeframe)
179
+ else:
180
+ timeframe = "Unknown Timeframe"
181
+
182
+ base_ticker = f"FOREX:{base_currency}"
183
+ quote_ticker = f"FOREX:{quote_currency}"
184
+
185
+ # Fetch and analyze sentiment data
186
+ json_response = fetch_sentiment_data(api_endpoint, f"{base_ticker}", api_key)
187
+ print(fetch_sentiment_data(api_endpoint, f"{quote_currency}", api_key))
188
+ print(json_response)
189
+ base_sentiment = analyze_sentiment(json_response, base_ticker)
190
+ quote_sentiment = analyze_sentiment(json_response, quote_currency)
191
+
192
+ # Make a trade decision based on technical and sentiment analysis
193
+ trade_decision, decision_reason = make_trade_decision(base_currency, quote_currency, quote_sentiment, base_sentiment)
194
+
195
+ signal = strategy.crossover[0]
196
+ if all(strategy.crossover[-i] == signal for i in range(1, consistent_periods + 1)):
197
+ #timeframe = bt.TimeFrame.getname(strategy.last_signal_timeframe) if strategy.last_signal_timeframe else "Unknown Timeframe"
198
+ return True, trade_decision, timeframe, decision_reason
199
+ return False, None, None, "Not enough consistent signals or conflicting sentiment " +decision_reason+"."
200
+
201
+ # Define a function to run the backtest and provide trading signals
202
+ def run_backtest(api_key, from_symbol, to_symbol, interval):
203
+ # Set up Cerebro engine
204
+ cerebro = bt.Cerebro()
205
+ cerebro.addstrategy(TrendFollowingStrategy)
206
+
207
+ # Add data feed to Cerebro
208
+ data = load_data(api_key, from_symbol, to_symbol, interval)
209
+ cerebro.adddata(data)
210
+
211
+ # Set initial cash (optional)
212
+ cerebro.broker.set_cash(10000)
213
+
214
+ # Run the backtest
215
+ strategy_instance = cerebro.run()[0]
216
+ api_endpoint = "https://www.alphavantage.co/query" # Replace with actual endpoint
217
+
218
+ # Calculate win and loss percentages
219
+ total_trades = strategy_instance.trade_count
220
+ total_wins = strategy_instance.win_count
221
+ total_losses = strategy_instance.loss_count
222
+
223
+ win_percentage = (total_wins / total_trades) * 100
224
+ loss_percentage = (total_losses / total_trades) * 100
225
+
226
+ # Determine if it's a buy or sell based on percentages
227
+ if win_percentage > loss_percentage:
228
+ signal = "Buy"
229
+ color = "green"
230
+ else:
231
+ signal = "Sell"
232
+ color = "red"
233
+
234
+ return f"Signal: <span style='color: {color}'>{signal}</span>"
235
+
236
+
237
+ # Define a list of popular currency pairs for the dropdowns
238
+ from_currency_choices = ['EUR', 'GBP', 'USD', 'AUD', 'JPY']
239
+ to_currency_choices = ['USD', 'JPY', 'GBP', 'AUD', 'CAD']
240
+
241
+ # Placeholder link for API key
242
+ api_key_link = "https://www.alphavantage.co/support/#api-key"
243
+
244
+ # Run the Gradio app
245
+ if __name__ == "__main__":
246
+ gr.Interface(
247
+ fn=run_backtest,
248
+ inputs=[
249
+ gr.inputs.Textbox(label="API Key", placeholder=api_key_link),
250
+ gr.inputs.Dropdown(label="From Currency", choices=from_currency_choices),
251
+ gr.inputs.Dropdown(label="To Currency", choices=to_currency_choices),
252
+ gr.inputs.Radio(label="Interval", choices=["1min", "5min", "15min", "30min", "60min"])
253
+ ],
254
+ outputs="html", # Output as HTML to display colored text
255
+ live=True,
256
+ title="Trading Signal",
257
+ description="Run Backtest and Get Trading Signal",
258
+ ).launch()
259
 
260
  iface = gr.Interface(fn=greet, inputs="text", outputs="text")
261
  iface.launch()
requirements.txt CHANGED
@@ -1 +1,4 @@
1
- gradio
 
 
 
 
1
+ gradio
2
+ pandas
3
+ backtrader
4
+ requests