{ "cells": [ { "metadata": { "SqlCellData": { "data_source_name": "leopard_dev@81.71.3.24", "variableName$1": "dailies_df" }, "ExecuteTime": { "end_time": "2026-01-20T02:26:30.134545Z", "start_time": "2026-01-20T02:26:22.978651Z" } }, "cell_type": "code", "source": [ "%%sql\n", "select trade_date, open * factor as Open, close * factor as Close, high * factor as High, low * factor as Low, volume as Volume, coalesce(factor, 1.0) as factor\n", "from leopard_daily daily\n", " left join leopard_stock stock on stock.id = daily.stock_id\n", "where stock.code = '000001.SZ'\n", " and daily.trade_date between '2025-01-01 00:00:00' and '2025-12-31 23:59:59'\n", "order by daily.trade_date" ], "id": "93e66142c88e4d2f", "outputs": [ { "data": { "text/plain": [ " trade_date open close high low \\\n", "0 2025-01-02 1498.907493 1460.572263 1504.018857 1455.460899 \n", "1 2025-01-03 1461.850104 1454.183058 1474.628514 1451.627376 \n", "2 2025-01-06 1454.183058 1461.850104 1466.961468 1433.737602 \n", "3 2025-01-07 1459.294422 1470.794991 1473.350673 1452.905217 \n", "4 2025-01-08 1469.517150 1469.517150 1486.129083 1456.738740 \n", ".. ... ... ... ... ... \n", "183 2025-10-09 1493.155774 1502.380920 1503.698798 1485.248506 \n", "184 2025-10-10 1498.427286 1506.334554 1514.241822 1497.109408 \n", "185 2025-10-13 1491.837896 1502.380920 1510.288188 1486.566384 \n", "186 2025-10-14 1501.063042 1524.784846 1528.738480 1497.109408 \n", "187 2025-10-15 1526.130396 1534.205160 1536.896748 1515.364044 \n", "\n", " volume factor \n", "0 1819596.99 127.7841 \n", "1 1154680.44 127.7841 \n", "2 1085536.30 127.7841 \n", "3 747862.88 127.7841 \n", "4 1062386.01 127.7841 \n", ".. ... ... \n", "183 1047469.06 131.7878 \n", "184 1087947.75 131.7878 \n", "185 1168801.73 131.7878 \n", "186 1843428.36 131.7878 \n", "187 1271061.03 134.5794 \n", "\n", "[188 rows x 7 columns]" ], "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
trade_dateopenclosehighlowvolumefactor
02025-01-021498.9074931460.5722631504.0188571455.4608991819596.99127.7841
12025-01-031461.8501041454.1830581474.6285141451.6273761154680.44127.7841
22025-01-061454.1830581461.8501041466.9614681433.7376021085536.30127.7841
32025-01-071459.2944221470.7949911473.3506731452.905217747862.88127.7841
42025-01-081469.5171501469.5171501486.1290831456.7387401062386.01127.7841
........................
1832025-10-091493.1557741502.3809201503.6987981485.2485061047469.06131.7878
1842025-10-101498.4272861506.3345541514.2418221497.1094081087947.75131.7878
1852025-10-131491.8378961502.3809201510.2881881486.5663841168801.73131.7878
1862025-10-141501.0630421524.7848461528.7384801497.1094081843428.36131.7878
1872025-10-151526.1303961534.2051601536.8967481515.3640441271061.03134.5794
\n", "

188 rows × 7 columns

\n", "
" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 87 }, { "metadata": { "ExecuteTime": { "end_time": "2026-01-20T02:26:30.368092Z", "start_time": "2026-01-20T02:26:30.241161Z" } }, "cell_type": "code", "source": [ "import pandas as pd\n", "\n", "dailies_df.rename(\n", " columns={'open': 'Open', 'close': 'Close', 'high': 'High', 'low': 'Low', 'volume': 'Volume'}, inplace=True\n", ")\n", "dailies_df['trade_date'] = pd.to_datetime(dailies_df['trade_date'], format='%Y-%m-%d')\n", "dailies_df.set_index('trade_date', inplace=True)\n", "dailies_df" ], "id": "c0ed078ffd5b57fd", "outputs": [ { "data": { "text/plain": [ " Open Close High Low Volume \\\n", "trade_date \n", "2025-01-02 1498.907493 1460.572263 1504.018857 1455.460899 1819596.99 \n", "2025-01-03 1461.850104 1454.183058 1474.628514 1451.627376 1154680.44 \n", "2025-01-06 1454.183058 1461.850104 1466.961468 1433.737602 1085536.30 \n", "2025-01-07 1459.294422 1470.794991 1473.350673 1452.905217 747862.88 \n", "2025-01-08 1469.517150 1469.517150 1486.129083 1456.738740 1062386.01 \n", "... ... ... ... ... ... \n", "2025-10-09 1493.155774 1502.380920 1503.698798 1485.248506 1047469.06 \n", "2025-10-10 1498.427286 1506.334554 1514.241822 1497.109408 1087947.75 \n", "2025-10-13 1491.837896 1502.380920 1510.288188 1486.566384 1168801.73 \n", "2025-10-14 1501.063042 1524.784846 1528.738480 1497.109408 1843428.36 \n", "2025-10-15 1526.130396 1534.205160 1536.896748 1515.364044 1271061.03 \n", "\n", " factor \n", "trade_date \n", "2025-01-02 127.7841 \n", "2025-01-03 127.7841 \n", "2025-01-06 127.7841 \n", "2025-01-07 127.7841 \n", "2025-01-08 127.7841 \n", "... ... \n", "2025-10-09 131.7878 \n", "2025-10-10 131.7878 \n", "2025-10-13 131.7878 \n", "2025-10-14 131.7878 \n", "2025-10-15 134.5794 \n", "\n", "[188 rows x 6 columns]" ], "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
OpenCloseHighLowVolumefactor
trade_date
2025-01-021498.9074931460.5722631504.0188571455.4608991819596.99127.7841
2025-01-031461.8501041454.1830581474.6285141451.6273761154680.44127.7841
2025-01-061454.1830581461.8501041466.9614681433.7376021085536.30127.7841
2025-01-071459.2944221470.7949911473.3506731452.905217747862.88127.7841
2025-01-081469.5171501469.5171501486.1290831456.7387401062386.01127.7841
.....................
2025-10-091493.1557741502.3809201503.6987981485.2485061047469.06131.7878
2025-10-101498.4272861506.3345541514.2418221497.1094081087947.75131.7878
2025-10-131491.8378961502.3809201510.2881881486.5663841168801.73131.7878
2025-10-141501.0630421524.7848461528.7384801497.1094081843428.36131.7878
2025-10-151526.1303961534.2051601536.8967481515.3640441271061.03134.5794
\n", "

188 rows × 6 columns

\n", "
" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 88 }, { "metadata": { "ExecuteTime": { "end_time": "2026-01-20T02:28:38.147008Z", "start_time": "2026-01-20T02:28:38.094513Z" } }, "cell_type": "code", "source": [ "dailies_df['sma30'] = dailies_df['Close'].rolling(10).mean()\n", "dailies_df['sma60'] = dailies_df['Close'].rolling(30).mean()\n", "dailies_df.tail()" ], "id": "c558d68773d228c1", "outputs": [ { "data": { "text/plain": [ " Open Close High Low Volume \\\n", "trade_date \n", "2025-10-09 1493.155774 1502.380920 1503.698798 1485.248506 1047469.06 \n", "2025-10-10 1498.427286 1506.334554 1514.241822 1497.109408 1087947.75 \n", "2025-10-13 1491.837896 1502.380920 1510.288188 1486.566384 1168801.73 \n", "2025-10-14 1501.063042 1524.784846 1528.738480 1497.109408 1843428.36 \n", "2025-10-15 1526.130396 1534.205160 1536.896748 1515.364044 1271061.03 \n", "\n", " factor sma30 sma60 \n", "trade_date \n", "2025-10-09 131.7878 1504.094161 1546.925196 \n", "2025-10-10 131.7878 1504.357737 1543.762289 \n", "2025-10-13 131.7878 1503.698798 1540.862958 \n", "2025-10-14 131.7878 1506.202766 1536.997182 \n", "2025-10-15 134.5794 1507.803737 1533.840781 " ], "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
OpenCloseHighLowVolumefactorsma30sma60
trade_date
2025-10-091493.1557741502.3809201503.6987981485.2485061047469.06131.78781504.0941611546.925196
2025-10-101498.4272861506.3345541514.2418221497.1094081087947.75131.78781504.3577371543.762289
2025-10-131491.8378961502.3809201510.2881881486.5663841168801.73131.78781503.6987981540.862958
2025-10-141501.0630421524.7848461528.7384801497.1094081843428.36131.78781506.2027661536.997182
2025-10-151526.1303961534.2051601536.8967481515.3640441271061.03134.57941507.8037371533.840781
\n", "
" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 97 }, { "metadata": { "ExecuteTime": { "end_time": "2026-01-20T02:28:09.232747Z", "start_time": "2026-01-20T02:28:09.215190Z" } }, "cell_type": "code", "source": [ "from backtesting import Strategy\n", "from backtesting.lib import crossover\n", "\n", "\n", "class SmaCross(Strategy):\n", " def init(self):\n", " pass\n", "\n", " def next(self):\n", " if crossover(self.data.sma30, self.data.sma60):\n", " self.position.close()\n", " self.buy()\n", " elif crossover(self.data.sma60, self.data.sma30):\n", " self.position.close()\n", " self.sell()" ], "id": "b56aaaf4cad7bc7d", "outputs": [], "execution_count": 94 }, { "metadata": { "ExecuteTime": { "end_time": "2026-01-20T02:28:12.350117Z", "start_time": "2026-01-20T02:28:12.330024Z" } }, "cell_type": "code", "source": [ "def stats_print(stats):\n", " indicator_name_mapping = {\n", " 'Start': '回测开始时间',\n", " 'End': '回测结束时间',\n", " 'Duration': '回测持续时长',\n", " 'Exposure Time [%]': '持仓时间占比(%)',\n", " 'Equity Final [$]': '最终权益',\n", " 'Equity Peak [$]': '权益峰值',\n", " 'Return [%]': '总收益率(%)',\n", " 'Buy & Hold Return [%]': '买入并持有收益率(%)',\n", " 'Return (Ann.) [%]': '年化收益率(%)',\n", " 'Volatility (Ann.) [%]': '年化波动率(%)',\n", " 'CAGR [%]': '复合年均增长率(%)',\n", " 'Sharpe Ratio': '夏普比率',\n", " 'Sortino Ratio': '索提诺比率',\n", " 'Calmar Ratio': '卡尔玛比率',\n", " 'Alpha [%]': '阿尔法系数(%)',\n", " 'Beta': '贝塔系数',\n", " 'Max. Drawdown [%]': '最大回撤(%)',\n", " 'Avg. Drawdown [%]': '平均回撤(%)',\n", " 'Max. Drawdown Duration': '最大回撤持续时长',\n", " 'Avg. Drawdown Duration': '平均回撤持续时长',\n", " '# Trades': '交易总次数',\n", " 'Win Rate [%]': '胜率(%)',\n", " 'Best Trade [%]': '最佳单笔交易收益率(%)',\n", " 'Worst Trade [%]': '最差单笔交易收益率(%)',\n", " 'Avg. Trade [%]': '平均单笔交易收益率(%)',\n", " 'Max. Trade Duration': '单笔交易最长持有时长',\n", " 'Avg. Trade Duration': '单笔交易平均持有时长',\n", " 'Profit Factor': '盈利因子',\n", " 'Expectancy [%]': '期望收益(%)',\n", " 'SQN': '系统质量数',\n", " 'Kelly Criterion': '凯利准则',\n", " }\n", " for k, v in stats.items():\n", " if k in indicator_name_mapping:\n", " cn_name = indicator_name_mapping.get(k, k)\n", " if isinstance(v, (int, float)):\n", " if \"%\" in cn_name or k in ['Sharpe Ratio', 'Sortino Ratio', 'Calmar Ratio', 'Profit Factor']:\n", " formatted_value = f\"{v:.2f}\"\n", " elif \"$\" in cn_name:\n", " formatted_value = f\"{v:.2f}\"\n", " elif \"次数\" in cn_name:\n", " formatted_value = f\"{v:.0f}\"\n", " else:\n", " formatted_value = f\"{v:.4f}\"\n", " else:\n", " formatted_value = str(v)\n", " print(f'{cn_name}: {formatted_value}')" ], "id": "a23e811212958477", "outputs": [], "execution_count": 95 }, { "metadata": { "ExecuteTime": { "end_time": "2026-01-20T02:28:43.128279Z", "start_time": "2026-01-20T02:28:43.044156Z" } }, "cell_type": "code", "source": [ "from backtesting import Backtest\n", "\n", "bt = Backtest(dailies_df, SmaCross, cash=100000, commission=.002, finalize_trades=True)\n", "stats = bt.run()\n", "stats_print(stats)" ], "id": "afc750727129ff2e", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "回测开始时间: 2025-01-02 00:00:00\n", "回测结束时间: 2025-10-15 00:00:00\n", "回测持续时长: 286 days 00:00:00\n", "持仓时间占比(%): 71.81\n", "最终权益: 114727.4805\n", "权益峰值: 117838.4813\n", "总收益率(%): 14.73\n", "买入并持有收益率(%): 5.04\n", "年化收益率(%): 20.22\n", "年化波动率(%): 17.17\n", "复合年均增长率(%): 12.87\n", "夏普比率: 1.18\n", "索提诺比率: 2.45\n", "卡尔玛比率: 2.21\n", "阿尔法系数(%): 14.96\n", "贝塔系数: -0.0456\n", "最大回撤(%): -9.13\n", "平均回撤(%): -3.40\n", "最大回撤持续时长: 97 days 00:00:00\n", "平均回撤持续时长: 33 days 00:00:00\n", "交易总次数: 3\n", "胜率(%): 66.67\n", "最佳单笔交易收益率(%): 10.02\n", "最差单笔交易收益率(%): -0.49\n", "平均单笔交易收益率(%): 4.76\n", "单笔交易最长持有时长: 78 days 00:00:00\n", "单笔交易平均持有时长: 68 days 00:00:00\n", "盈利因子: 30.80\n", "期望收益(%): 4.84\n", "系统质量数: 1.6469\n", "凯利准则: 0.6455\n" ] } ], "execution_count": 98 } ], "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": 5 }