-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathml_stock_sentiment.py
155 lines (130 loc) · 5.64 KB
/
ml_stock_sentiment.py
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import streamlit as st
import threading
from datetime import datetime
# LumiBot imports v1
from lumibot.backtesting import YahooDataBacktesting
from lumibot.brokers import Alpaca
from lumibot.traders import Trader
from lumibot.credentials import ALPACA_CREDS
# Import your strategy (example)
from lumibot.example_strategies.stock_sentiment import StockSentiment
st.set_page_config(
page_title='Finance ML',
layout="wide",
page_icon=':bar_chart:',
)
st.title("Sentiment-Based Trading Bot with Live Trading")
st.subheader("FinBERT pre-trained NLP model to analyze sentiment of financial text.")
st.write("""
Automated sentiment or polarity analysis of texts produced by financial actors using NLP methods.
This strategy uses FinBERT to analyze the sentiment of financial news and make trading decisions based on the sentiment score.
""")
# Store results in session_state so we can display them from the main thread
if "backtest_results" not in st.session_state:
st.session_state["backtest_results"] = None
if "tear_sheet_figure" not in st.session_state:
st.session_state["tear_sheet_figure"] = None
if "backtest_running" not in st.session_state:
st.session_state["backtest_running"] = False
# UI Elements for user interaction in the main view
st.header("Strategy Parameters")
# Select backtest period
col1, col2 = st.columns(2)
with col1:
start_date = st.date_input("Start Date", datetime(2020, 1, 1))
with col2:
end_date = st.date_input("End Date", datetime(2020, 11, 12))
# Select stock symbol
symbol = st.selectbox("Select Stock Symbol", ["SPY", "AAPL", "GOOGL", "AMZN", "TSLA"])
# Set cash at risk
cash_at_risk = st.slider("Cash at Risk (%)", 0.1, 1.0, 0.5)
# Button to run sentiment analysis
if st.button("Run Sentiment Analysis"):
st.write(f"Running sentiment analysis for {symbol} from {start_date} to {end_date} with {cash_at_risk * 100}% cash at risk...")
# Here you would call the sentiment analysis function and store the results
# Button to view sentiment results and trading decisions
if st.button("View Sentiment Results"):
if st.session_state["backtest_results"] is not None:
st.write("### Sentiment Results")
st.write(st.session_state["backtest_results"])
else:
st.warning("No sentiment results available. Please run the sentiment analysis first.")
def run_backtest():
"""Long-running backtest & live trading in a background thread."""
try:
st.session_state["backtest_running"] = True
# Define the backtest period
start_date = datetime(2020,1,1)
end_date = datetime(2020,11,12)
print(f"[Thread] Starting backtest from {start_date} to {end_date}...")
# Set up broker and strategy
broker = Alpaca(ALPACA_CREDS)
strategy = StockSentiment(
name="mlstrat",
broker=broker,
parameters={
"symbol": symbol,
"cash_at_risk": cash_at_risk
}
)
# Run the backtest
results = strategy.backtest(
YahooDataBacktesting,
start_date,
end_date,
parameters={"symbol": symbol, "cash_at_risk": cash_at_risk},
)
st.session_state["backtest_results"] = results
# OPTIONAL: Generate a tear sheet if LumiBot (or you) provide a function
if hasattr(results, "create_tear_sheet"):
fig = results.create_tear_sheet()
st.session_state["tear_sheet_figure"] = fig
elif hasattr(results, "display_tear_sheet"):
# If display_tear_sheet returns a figure
fig = results.display_tear_sheet(return_fig=True)
st.session_state["tear_sheet_figure"] = fig
else:
# If there's no tear sheet method, you'll need custom logic:
print("[Thread] No tear sheet method found in results.")
st.session_state["tear_sheet_figure"] = None
print("[Thread] Backtest finished. Starting live trading...")
# Start live trading (This is a blocking call)
trader = Trader()
trader.add_strategy(strategy)
# Start the trading in a separate thread to avoid blocking Streamlit
trader_thread = threading.Thread(target=trader.run_all)
trader_thread.start()
# Display a progress bar in the Streamlit app
while trader_thread.is_alive():
st.progress(100 * (1 - trader_thread._stop.__self__.is_alive()))
st.write("Running live trading...")
finally:
st.session_state["backtest_running"] = False
def start_background_backtest():
# Reset old results
st.session_state["backtest_results"] = None
st.session_state["tear_sheet_figure"] = None
# Start a thread to run the backtest
worker_thread = threading.Thread(target=run_backtest, args=())
worker_thread.start()
# Button to trigger backtest
if st.button("Start Backtest"):
# Prevent multiple backtest runs
if not st.session_state["backtest_running"]:
st.write("Backtest is starting in the background...")
start_background_backtest()
else:
st.warning("A backtest is already running!")
# Status / Results display
if st.session_state["backtest_running"]:
st.info("Backtest is running... (this might take a while).")
elif st.session_state["backtest_results"] is not None:
st.success("Backtest completed!")
st.write("### Backtest Results")
st.write(st.session_state["backtest_results"])
# Display the tear sheet if we have it
if st.session_state["tear_sheet_figure"] is not None:
st.write("### Tear Sheet")
st.pyplot(st.session_state["tear_sheet_figure"])
else:
st.warning("No tear sheet figure available.")