diff --git a/main.py b/main.py index af7e626..c9495f6 100644 --- a/main.py +++ b/main.py @@ -27,16 +27,15 @@ if st.session_state["authentication_status"]: Page("main.py", "Hummingbot Dashboard", "๐Ÿ“Š"), Section("Bot Orchestration", "๐Ÿ™"), Page("pages/master_conf/app.py", "Credentials", "๐Ÿ—๏ธ"), - Page("pages/launch_bot/app.py", "Launch Bot", "๐Ÿ™Œ"), Page("pages/bot_orchestration/app.py", "Instances", "๐Ÿฆ…"), - Page("pages/file_manager/app.py", "Strategy Configs", "๐Ÿ—‚"), + Page("pages/file_manager/app.py", "File Explorer", "๐Ÿ—‚"), Section("Backtest Manager", "โš™๏ธ"), Page("pages/candles_downloader/app.py", "Get Data", "๐Ÿ’พ"), Page("pages/backtest_manager/create.py", "Create", "โš”๏ธ"), Page("pages/backtest_manager/optimize.py", "Optimize", "๐Ÿงช"), Page("pages/backtest_manager/analyze.py", "Analyze", "๐Ÿ”ฌ"), - Page("pages/backtest_manager/analyze_v2.py", "Analyze v2", "๐Ÿ”ฌ"), Page("pages/backtest_manager/simulate.py", "Simulate", "๐Ÿ“ˆ"), + Page("pages/launch_bot/app.py", "Deploy", "๐Ÿ™Œ"), Section("Community Pages", "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ"), Page("pages/strategy_performance/app.py", "Strategy Performance", "๐Ÿš€"), Page("pages/db_inspector/app.py", "DB Inspector", "๐Ÿ”"), diff --git a/pages/backtest_manager/analyze_v2.py b/pages/backtest_manager/analyze_v2.py deleted file mode 100644 index e5111ce..0000000 --- a/pages/backtest_manager/analyze_v2.py +++ /dev/null @@ -1,227 +0,0 @@ -from hummingbot.core.data_type.common import PositionMode, TradeType, OrderType -from hummingbot.data_feed.candles_feed.candles_factory import CandlesConfig -from hummingbot.smart_components.strategy_frameworks.data_types import OrderLevel, TripleBarrierConf -from hummingbot.smart_components.strategy_frameworks.directional_trading import DirectionalTradingBacktestingEngine -from hummingbot.smart_components.utils import ConfigEncoderDecoder - -import constants -import os -import json -import streamlit as st -from decimal import Decimal - -from quants_lab.strategy.strategy_analysis import StrategyAnalysis -from utils.graphs import BacktestingGraphs -from utils.optuna_database_manager import OptunaDBManager -from utils.os_utils import load_controllers -from utils.st_utils import initialize_st_page - - -initialize_st_page(title="Analyze", icon="๐Ÿ”ฌ", initial_sidebar_state="collapsed") - - -@st.cache_resource -def get_databases(): - sqlite_files = [db_name for db_name in os.listdir("data/backtesting") if db_name.endswith(".db")] - databases_list = [OptunaDBManager(db) for db in sqlite_files] - databases_dict = {database.db_name: database for database in databases_list} - return [x.db_name for x in databases_dict.values() if x.status == 'OK'] - - -def initialize_session_state_vars(): - if "strategy_params" not in st.session_state: - st.session_state.strategy_params = {} - if "backtesting_params" not in st.session_state: - st.session_state.backtesting_params = {} - - -initialize_session_state_vars() -dbs = get_databases() -if not dbs: - st.warning("We couldn't find any Optuna database.") - selected_db_name = None - selected_db = None -else: - # Select database from selectbox - selected_db = st.selectbox("Select your database:", dbs) - # Instantiate database manager - opt_db = OptunaDBManager(selected_db) - # Load studies - studies = opt_db.load_studies() - # Choose study - study_selected = st.selectbox("Select a study:", studies.keys()) - # Filter trials from selected study - merged_df = opt_db.merged_df[opt_db.merged_df["study_name"] == study_selected] - filters_column, scatter_column = st.columns([1, 6]) - with filters_column: - accuracy = st.slider("Accuracy", min_value=0.0, max_value=1.0, value=[0.4, 1.0], step=0.01) - net_profit = st.slider("Net PNL (%)", min_value=merged_df["net_pnl_pct"].min(), max_value=merged_df["net_pnl_pct"].max(), - value=[merged_df["net_pnl_pct"].min(), merged_df["net_pnl_pct"].max()], step=0.01) - max_drawdown = st.slider("Max Drawdown (%)", min_value=merged_df["max_drawdown_pct"].min(), max_value=merged_df["max_drawdown_pct"].max(), - value=[merged_df["max_drawdown_pct"].min(), merged_df["max_drawdown_pct"].max()], step=0.01) - total_positions = st.slider("Total Positions", min_value=merged_df["total_positions"].min(), max_value=merged_df["total_positions"].max(), - value=[merged_df["total_positions"].min(), merged_df["total_positions"].max()], step=1) - net_profit_filter = (merged_df["net_pnl_pct"] >= net_profit[0]) & (merged_df["net_pnl_pct"] <= net_profit[1]) - accuracy_filter = (merged_df["accuracy"] >= accuracy[0]) & (merged_df["accuracy"] <= accuracy[1]) - max_drawdown_filter = (merged_df["max_drawdown_pct"] >= max_drawdown[0]) & (merged_df["max_drawdown_pct"] <= max_drawdown[1]) - total_positions_filter = (merged_df["total_positions"] >= total_positions[0]) & (merged_df["total_positions"] <= total_positions[1]) - with scatter_column: - bt_graphs = BacktestingGraphs(merged_df[net_profit_filter & accuracy_filter & max_drawdown_filter & total_positions_filter]) - # Show and compare all of the study trials - st.plotly_chart(bt_graphs.pnl_vs_maxdrawdown(), use_container_width=True) - # Get study trials - trials = studies[study_selected] - # Choose trial - trial_selected = st.selectbox("Select a trial to backtest", list(trials.keys())) - trial = trials[trial_selected] - # Transform trial config in a dictionary - encoder_decoder = ConfigEncoderDecoder(TradeType, OrderType, PositionMode) - trial_config = encoder_decoder.decode(json.loads(trial["config"])) - - # Strategy parameters section - st.write("## Strategy parameters") - # Load strategies (class, config, module) - controllers = load_controllers(constants.CONTROLLERS_PATH) - # Select strategy - controller = controllers[trial_config["strategy_name"]] - # Get field schema - field_schema = controller["config"].schema()["properties"] - - columns = st.columns(4) - column_index = 0 - for field_name, properties in field_schema.items(): - field_type = properties.get("type", "string") - field_value = trial_config[field_name] - if field_name not in ["candles_config", "order_levels", "position_mode"]: - with columns[column_index]: - if field_type in ["number", "integer"]: - field_value = st.number_input(field_name, - value=field_value, - min_value=properties.get("minimum"), - max_value=properties.get("maximum"), - key=field_name) - elif field_type == "string": - field_value = st.text_input(field_name, value=field_value) - elif field_type == "boolean": - # TODO: Add support for boolean fields in optimize tab - field_value = st.checkbox(field_name, value=field_value) - else: - raise ValueError(f"Field type {field_type} not supported") - else: - if field_name == "candles_config": - st.write("---") - st.write(f"## Candles Config:") - candles = [] - for i, candles_config in enumerate(field_value): - st.write(f"#### Candle {i}:") - c11, c12, c13, c14 = st.columns(4) - with c11: - connector = st.text_input("Connector", value=candles_config["connector"]) - with c12: - trading_pair = st.text_input("Trading pair", value=candles_config["trading_pair"]) - with c13: - interval = st.text_input("Interval", value=candles_config["interval"]) - with c14: - max_records = st.number_input("Max records", value=candles_config["max_records"]) - st.write("---") - candles.append(CandlesConfig(connector=connector, trading_pair=trading_pair, interval=interval, - max_records=max_records)) - field_value = candles - elif field_name == "order_levels": - new_levels = [] - st.write(f"## Order Levels:") - for order_level in field_value: - st.write(f"### Level {order_level['level']} {order_level['side'].name}") - ol_c1, ol_c2 = st.columns([5, 1]) - with ol_c1: - st.write("#### Triple Barrier config:") - c21, c22, c23, c24, c25 = st.columns(5) - triple_barrier_conf_level = order_level["triple_barrier_conf"] - with c21: - take_profit = st.number_input("Take profit", value=float(triple_barrier_conf_level["take_profit"]), - key=f"{order_level['level']}_{order_level['side'].name}_tp") - with c22: - stop_loss = st.number_input("Stop Loss", value=float(triple_barrier_conf_level["stop_loss"]), - key=f"{order_level['level']}_{order_level['side'].name}_sl") - with c23: - time_limit = st.number_input("Time Limit", value=triple_barrier_conf_level["time_limit"], - key=f"{order_level['level']}_{order_level['side'].name}_tl") - with c24: - ts_ap = st.number_input("Trailing Stop Activation Price", value=float(triple_barrier_conf_level["trailing_stop_activation_price_delta"]), - key=f"{order_level['level']}_{order_level['side'].name}_tsap", format="%.4f") - with c25: - ts_td = st.number_input("Trailing Stop Trailing Delta", value=float(triple_barrier_conf_level["trailing_stop_trailing_delta"]), - key=f"{order_level['level']}_{order_level['side'].name}_tstd", format="%.4f") - with ol_c2: - st.write("#### Position config:") - c31, c32 = st.columns(2) - with c31: - order_amount = st.number_input("Order amount USD", value=float(order_level["order_amount_usd"]), - key=f"{order_level['level']}_{order_level['side'].name}_oa") - with c32: - cooldown_time = st.number_input("Cooldown time", value=order_level["cooldown_time"], - key=f"{order_level['level']}_{order_level['side'].name}_cd") - triple_barrier_conf = TripleBarrierConf(stop_loss=Decimal(stop_loss), take_profit=Decimal(take_profit), - time_limit=time_limit, - trailing_stop_activation_price_delta=Decimal(ts_ap), - trailing_stop_trailing_delta=Decimal(ts_td), - open_order_type=OrderType.MARKET) - new_levels.append(OrderLevel(level=order_level["level"], side=order_level["side"], - order_amount_usd=order_amount, cooldown_time=cooldown_time, - triple_barrier_conf=triple_barrier_conf)) - st.write("---") - - field_value = new_levels - elif field_name == "position_mode": - field_value = PositionMode.HEDGE - else: - field_value = None - st.session_state["strategy_params"][field_name] = field_value - - column_index = (column_index + 1) % 4 - - st.write("### Backtesting period") - col1, col2, col3, col4 = st.columns([1, 1, 1, 0.5]) - with col1: - trade_cost = st.number_input("Trade cost", - value=0.0006, - min_value=0.0001, format="%.4f", ) - with col2: - initial_portfolio_usd = st.number_input("Initial portfolio usd", - value=10000.00, - min_value=1.00, - max_value=999999999.99) - with col3: - start = st.text_input("Start", value="2023-01-01") - end = st.text_input("End", value="2023-08-01") - c1, c2 = st.columns([1, 1]) - with col4: - add_positions = st.checkbox("Add positions", value=True) - add_volume = st.checkbox("Add volume", value=True) - add_pnl = st.checkbox("Add PnL", value=True) - save_config = st.button("๐Ÿ’พSave controller config!") - config = controller["config"](**st.session_state["strategy_params"]) - controller = controller["class"](config=config) - if save_config: - encoder_decoder = ConfigEncoderDecoder(TradeType, OrderType, PositionMode) - encoder_decoder.yaml_dump(config.dict(), - f"hummingbot_files/controller_configs/{config.strategy_name}_{trial_selected}.yml") - run_backtesting_button = st.button("โš™๏ธRun Backtesting!") - if run_backtesting_button: - try: - engine = DirectionalTradingBacktestingEngine(controller=controller) - engine.load_controller_data("./data/candles") - backtesting_results = engine.run_backtesting(initial_portfolio_usd=initial_portfolio_usd, - trade_cost=trade_cost, - start=start, end=end) - strategy_analysis = StrategyAnalysis( - positions=backtesting_results["executors_df"], - candles_df=backtesting_results["processed_data"], - ) - metrics_container = BacktestingGraphs(backtesting_results["processed_data"]).get_trial_metrics( - strategy_analysis, - add_positions=add_positions, - add_volume=add_volume) - - except FileNotFoundError: - st.warning(f"The requested candles could not be found.")