diff --git a/quants_lab/research_notebooks/supertrend_multitimeframe/03_optimization_notebook.ipynb b/quants_lab/research_notebooks/supertrend_multitimeframe/03_optimization_notebook.ipynb new file mode 100644 index 0000000..91c9894 --- /dev/null +++ b/quants_lab/research_notebooks/supertrend_multitimeframe/03_optimization_notebook.ipynb @@ -0,0 +1,241 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "\n", + "root_path = os.path.abspath(os.path.join(os.getcwd(), '../../..'))\n", + "sys.path.append(root_path)" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 2, + "outputs": [], + "source": [ + "import traceback\n", + "from decimal import Decimal\n", + "import pandas_ta as ta # noqa: F401\n", + "\n", + "from hummingbot.core.data_type.common import PositionMode, TradeType, OrderType\n", + "from hummingbot.data_feed.candles_feed.candles_factory import CandlesConfig\n", + "from hummingbot.smart_components.strategy_frameworks.data_types import TripleBarrierConf, OrderLevel\n", + "from hummingbot.smart_components.strategy_frameworks.directional_trading import DirectionalTradingBacktestingEngine\n", + "from hummingbot.smart_components.utils.config_encoder_decoder import ConfigEncoderDecoder\n", + "from optuna import TrialPruned\n", + "from hummingbot.smart_components.utils.order_level_builder import OrderLevelBuilder\n", + "\n", + "from quants_lab.controllers.supertrend_multitimeframe import SuperTrendMT, SuperTrendMTConfig\n", + "\n", + "# To run an optimization with optuna we need to define the objective function that will be executed for each trial\n", + "\n", + "def objective(trial):\n", + " try:\n", + " # Market configuration\n", + " exchange = \"binance_perpetual\"\n", + " trading_pair = \"WLD-USDT\"\n", + " intervals = [\"3m\", \"1h\"]\n", + "\n", + " # Account configuration\n", + " initial_portfolio_usd = 1000\n", + " order_amount = Decimal(\"25\")\n", + " n_levels = 1\n", + " leverage = 20\n", + " trade_cost = 0.0006\n", + "\n", + " # Backtest period\n", + " start = \"2023-01-01\"\n", + " end = \"2024-01-02\"\n", + "\n", + " # Triple barrier configuration\n", + " stop_loss = trial.suggest_float('stop_loss', 0.01, 0.02, step=0.01)\n", + " take_profit = trial.suggest_float('take_profit', 0.01, 0.04, step=0.01)\n", + " time_limit = 60 * 60 * 12 # 12 hours\n", + " trailing_stop_activation_price_delta = Decimal(\"0.008\")\n", + " trailing_stop_trailing_delta = Decimal(\"0.004\")\n", + "\n", + " length = trial.suggest_int('length', 20, 200, step=20)\n", + " multiplier = trial.suggest_float('multiplier', 2.0, 6.0, step=1.0)\n", + " percentage_threshold = trial.suggest_float('percentage_threshold', 0.01, 0.03, step=0.01)\n", + "\n", + " # Building the order levels\n", + " order_level_builder = OrderLevelBuilder(n_levels=n_levels)\n", + " order_levels = order_level_builder.build_order_levels(\n", + " amounts=order_amount,\n", + " spreads=Decimal(\"0\"),\n", + " triple_barrier_confs=TripleBarrierConf(\n", + " stop_loss=stop_loss, take_profit=take_profit, time_limit=time_limit,\n", + " trailing_stop_activation_price_delta=trailing_stop_activation_price_delta,\n", + " trailing_stop_trailing_delta=trailing_stop_trailing_delta),\n", + " )\n", + " config = SuperTrendMTConfig(\n", + " exchange=exchange,\n", + " trading_pair=trading_pair,\n", + " strategy_name='supertrend_multitimeframe',\n", + " candles_config=[\n", + " CandlesConfig(connector=exchange, trading_pair=trading_pair,\n", + " interval=intervals[0], max_records=sys.maxsize),\n", + " CandlesConfig(connector=exchange, trading_pair=trading_pair,\n", + " interval=intervals[1], max_records=sys.maxsize),\n", + " ],\n", + " order_levels=order_levels,\n", + " leverage=leverage,\n", + " position_mode=PositionMode.HEDGE,\n", + " length=length,\n", + " multiplier=multiplier,\n", + " percentage_threshold=percentage_threshold,\n", + "\n", + " )\n", + " controller = SuperTrendMT(config=config)\n", + " engine = DirectionalTradingBacktestingEngine(controller=controller)\n", + " engine.load_controller_data(\"../../../data/candles\")\n", + " backtesting_results = engine.run_backtesting(\n", + " initial_portfolio_usd=initial_portfolio_usd,\n", + " trade_cost=trade_cost,\n", + " start=start, end=end)\n", + "\n", + " strategy_analysis = backtesting_results[\"results\"]\n", + " encoder_decoder = ConfigEncoderDecoder(TradeType, OrderType, PositionMode)\n", + "\n", + " trial.set_user_attr(\"net_pnl_quote\", strategy_analysis[\"net_pnl_quote\"])\n", + " trial.set_user_attr(\"net_pnl_pct\", strategy_analysis[\"net_pnl\"])\n", + " trial.set_user_attr(\"max_drawdown_usd\", strategy_analysis[\"max_drawdown_usd\"])\n", + " trial.set_user_attr(\"max_drawdown_pct\", strategy_analysis[\"max_drawdown_pct\"])\n", + " trial.set_user_attr(\"sharpe_ratio\", strategy_analysis[\"sharpe_ratio\"])\n", + " trial.set_user_attr(\"accuracy\", strategy_analysis[\"accuracy\"])\n", + " trial.set_user_attr(\"total_positions\", strategy_analysis[\"total_positions\"])\n", + " trial.set_user_attr(\"profit_factor\", strategy_analysis[\"profit_factor\"])\n", + " trial.set_user_attr(\"duration_in_hours\", strategy_analysis[\"duration_minutes\"] / 60)\n", + " trial.set_user_attr(\"avg_trading_time_in_hours\", strategy_analysis[\"avg_trading_time_minutes\"] / 60)\n", + " trial.set_user_attr(\"win_signals\", strategy_analysis[\"win_signals\"])\n", + " trial.set_user_attr(\"loss_signals\", strategy_analysis[\"loss_signals\"])\n", + " trial.set_user_attr(\"config\", encoder_decoder.encode(config.dict()))\n", + " return strategy_analysis[\"net_pnl\"]\n", + " except Exception as e:\n", + " traceback.print_exc()\n", + " raise TrialPruned()\n" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-12-12T01:02:29.309413Z", + "start_time": "2023-12-12T01:02:29.300687Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 4, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[I 2023-12-11 22:02:37,318] A new study created in RDB with name: super_trend_optimization_mt\n" + ] + } + ], + "source": [ + "import optuna\n", + "\n", + "# Now let's configure the parameters for the optimization\n", + "study_name = \"super_trend_optimization_mt\"\n", + "storage= \"sqlite:///../../../data/backtesting/backtesting_report.db\"\n", + "\n", + "study = optuna.create_study(direction=\"maximize\", study_name=study_name,\n", + " storage=storage,\n", + " load_if_exists=True # If the study already exists, we load it\n", + " )" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-12-12T01:02:37.322291Z", + "start_time": "2023-12-12T01:02:37.245002Z" + } + } + }, + { + "cell_type": "code", + "execution_count": 5, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[I 2023-12-11 22:03:00,563] Trial 0 finished with value: -0.35098199626293336 and parameters: {'stop_loss': 0.02, 'take_profit': 0.02, 'length': 40, 'multiplier': 6.0, 'percentage_threshold': 0.03}. Best is trial 0 with value: -0.35098199626293336.\n", + "[I 2023-12-11 22:03:17,061] Trial 1 finished with value: 0.12488305093272298 and parameters: {'stop_loss': 0.02, 'take_profit': 0.03, 'length': 140, 'multiplier': 3.0, 'percentage_threshold': 0.01}. Best is trial 1 with value: 0.12488305093272298.\n", + "[I 2023-12-11 22:03:33,423] Trial 2 finished with value: -0.4536291130718499 and parameters: {'stop_loss': 0.01, 'take_profit': 0.02, 'length': 120, 'multiplier': 5.0, 'percentage_threshold': 0.02}. Best is trial 1 with value: 0.12488305093272298.\n", + "[I 2023-12-11 22:03:49,953] Trial 3 finished with value: -0.05073410868582624 and parameters: {'stop_loss': 0.01, 'take_profit': 0.03, 'length': 100, 'multiplier': 4.0, 'percentage_threshold': 0.01}. Best is trial 1 with value: 0.12488305093272298.\n", + "[I 2023-12-11 22:04:07,164] Trial 4 finished with value: 0.1619153622180836 and parameters: {'stop_loss': 0.02, 'take_profit': 0.03, 'length': 200, 'multiplier': 6.0, 'percentage_threshold': 0.01}. Best is trial 4 with value: 0.1619153622180836.\n", + "[I 2023-12-11 22:04:24,073] Trial 5 finished with value: -0.18547605063707406 and parameters: {'stop_loss': 0.02, 'take_profit': 0.01, 'length': 40, 'multiplier': 3.0, 'percentage_threshold': 0.02}. Best is trial 4 with value: 0.1619153622180836.\n", + "[I 2023-12-11 22:04:41,109] Trial 6 finished with value: -0.3164755434895661 and parameters: {'stop_loss': 0.02, 'take_profit': 0.01, 'length': 180, 'multiplier': 6.0, 'percentage_threshold': 0.01}. Best is trial 4 with value: 0.1619153622180836.\n", + "[I 2023-12-11 22:04:57,609] Trial 7 finished with value: -0.1038527397065552 and parameters: {'stop_loss': 0.01, 'take_profit': 0.02, 'length': 140, 'multiplier': 4.0, 'percentage_threshold': 0.03}. Best is trial 4 with value: 0.1619153622180836.\n", + "[I 2023-12-11 22:05:15,271] Trial 8 finished with value: 0.7404879450347805 and parameters: {'stop_loss': 0.01, 'take_profit': 0.01, 'length': 40, 'multiplier': 2.0, 'percentage_threshold': 0.01}. Best is trial 8 with value: 0.7404879450347805.\n", + "[I 2023-12-11 22:05:33,215] Trial 9 finished with value: -0.960719787819319 and parameters: {'stop_loss': 0.01, 'take_profit': 0.01, 'length': 60, 'multiplier': 6.0, 'percentage_threshold': 0.01}. Best is trial 8 with value: 0.7404879450347805.\n", + "[I 2023-12-11 22:05:50,582] Trial 10 finished with value: 1.1998584529952074 and parameters: {'stop_loss': 0.01, 'take_profit': 0.04, 'length': 80, 'multiplier': 2.0, 'percentage_threshold': 0.02}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:06:07,814] Trial 11 finished with value: 1.1998584529952074 and parameters: {'stop_loss': 0.01, 'take_profit': 0.04, 'length': 80, 'multiplier': 2.0, 'percentage_threshold': 0.02}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:06:24,455] Trial 12 finished with value: 1.1998584529952074 and parameters: {'stop_loss': 0.01, 'take_profit': 0.04, 'length': 80, 'multiplier': 2.0, 'percentage_threshold': 0.02}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:06:41,101] Trial 13 finished with value: 1.1998584529952074 and parameters: {'stop_loss': 0.01, 'take_profit': 0.04, 'length': 80, 'multiplier': 2.0, 'percentage_threshold': 0.02}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:06:57,606] Trial 14 finished with value: 0.02047001353630673 and parameters: {'stop_loss': 0.01, 'take_profit': 0.04, 'length': 20, 'multiplier': 3.0, 'percentage_threshold': 0.03}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:07:14,208] Trial 15 finished with value: 0.9931433766610962 and parameters: {'stop_loss': 0.01, 'take_profit': 0.04, 'length': 100, 'multiplier': 2.0, 'percentage_threshold': 0.02}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:07:30,823] Trial 16 finished with value: 0.37864993105614836 and parameters: {'stop_loss': 0.01, 'take_profit': 0.03, 'length': 80, 'multiplier': 3.0, 'percentage_threshold': 0.02}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:07:47,525] Trial 17 finished with value: 1.089455391608849 and parameters: {'stop_loss': 0.01, 'take_profit': 0.04, 'length': 140, 'multiplier': 2.0, 'percentage_threshold': 0.03}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:08:04,394] Trial 18 finished with value: -0.2011129787326267 and parameters: {'stop_loss': 0.01, 'take_profit': 0.04, 'length': 60, 'multiplier': 5.0, 'percentage_threshold': 0.02}. Best is trial 10 with value: 1.1998584529952074.\n", + "[I 2023-12-11 22:08:20,927] Trial 19 finished with value: 0.19209940796981184 and parameters: {'stop_loss': 0.01, 'take_profit': 0.03, 'length': 120, 'multiplier': 3.0, 'percentage_threshold': 0.02}. Best is trial 10 with value: 1.1998584529952074.\n" + ] + } + ], + "source": [ + "# Not let's run the optimization!\n", + "\n", + "n_trials = 20\n", + "study.optimize(objective, n_trials=n_trials)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-12-12T01:08:20.930649Z", + "start_time": "2023-12-12T01:02:43.228031Z" + } + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [], + "metadata": { + "collapsed": false + } + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}