1
0

完成回测的基本计算

This commit is contained in:
2026-01-20 10:29:43 +08:00
parent 36db9d05ea
commit 04a3fbdf8e
5 changed files with 906 additions and 376 deletions

View File

@@ -2,262 +2,260 @@
"cells": [
{
"metadata": {
"SqlCellData": {
"data_source_name": "leopard_dev@81.71.3.24",
"variableName$1": "dailies_df"
},
"ExecuteTime": {
"end_time": "2026-01-19T10:00:35.820002Z",
"start_time": "2026-01-19T10:00:34.354216Z"
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>trade_date</th>\n",
" <th>open</th>\n",
" <th>close</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>volume</th>\n",
" <th>factor</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-01-02</td>\n",
" <td>1498.907493</td>\n",
" <td>1460.572263</td>\n",
" <td>1504.018857</td>\n",
" <td>1455.460899</td>\n",
" <td>1819596.99</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-01-03</td>\n",
" <td>1461.850104</td>\n",
" <td>1454.183058</td>\n",
" <td>1474.628514</td>\n",
" <td>1451.627376</td>\n",
" <td>1154680.44</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2025-01-06</td>\n",
" <td>1454.183058</td>\n",
" <td>1461.850104</td>\n",
" <td>1466.961468</td>\n",
" <td>1433.737602</td>\n",
" <td>1085536.30</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2025-01-07</td>\n",
" <td>1459.294422</td>\n",
" <td>1470.794991</td>\n",
" <td>1473.350673</td>\n",
" <td>1452.905217</td>\n",
" <td>747862.88</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2025-01-08</td>\n",
" <td>1469.517150</td>\n",
" <td>1469.517150</td>\n",
" <td>1486.129083</td>\n",
" <td>1456.738740</td>\n",
" <td>1062386.01</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>183</th>\n",
" <td>2025-10-09</td>\n",
" <td>1493.155774</td>\n",
" <td>1502.380920</td>\n",
" <td>1503.698798</td>\n",
" <td>1485.248506</td>\n",
" <td>1047469.06</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>184</th>\n",
" <td>2025-10-10</td>\n",
" <td>1498.427286</td>\n",
" <td>1506.334554</td>\n",
" <td>1514.241822</td>\n",
" <td>1497.109408</td>\n",
" <td>1087947.75</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>185</th>\n",
" <td>2025-10-13</td>\n",
" <td>1491.837896</td>\n",
" <td>1502.380920</td>\n",
" <td>1510.288188</td>\n",
" <td>1486.566384</td>\n",
" <td>1168801.73</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>186</th>\n",
" <td>2025-10-14</td>\n",
" <td>1501.063042</td>\n",
" <td>1524.784846</td>\n",
" <td>1528.738480</td>\n",
" <td>1497.109408</td>\n",
" <td>1843428.36</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>187</th>\n",
" <td>2025-10-15</td>\n",
" <td>1526.130396</td>\n",
" <td>1534.205160</td>\n",
" <td>1536.896748</td>\n",
" <td>1515.364044</td>\n",
" <td>1271061.03</td>\n",
" <td>134.5794</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>188 rows × 7 columns</p>\n",
"</div>"
]
},
"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",
"host = '81.71.3.24'\n",
"port = 6785\n",
"database = 'leopard_dev'\n",
"username = 'leopard'\n",
"password = '9NEzFzovnddf@PyEP?e*AYAWnCyd7UhYwQK$pJf>7?ccFiN^x4$eKEZ5~E<7<+~X'"
],
"id": "d815a3591c4f9463",
"outputs": [],
"execution_count": 2
},
{
"cell_type": "code",
"id": "initial_id",
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2026-01-19T10:00:42.739695Z",
"start_time": "2026-01-19T10:00:35.820726Z"
}
},
"source": [
"import psycopg2\n",
"\n",
"dailies_df = pd.DataFrame()\n",
"\n",
"with psycopg2.connect(host=host, port=port, database=database, user=username, password=password) as connection:\n",
" with connection.cursor() as cursor:\n",
" # language=PostgreSQL\n",
" cursor.execute(\n",
" \"\"\"select trade_date, open, close, high, low, 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\"\"\"\n",
"dailies_df.rename(\n",
" columns={'open': 'Open', 'close': 'Close', 'high': 'High', 'low': 'Low', 'volume': 'Volume'}, inplace=True\n",
")\n",
" rows = cursor.fetchall()\n",
"\n",
" dailies_df = pd.DataFrame.from_records(rows, columns=['trade_date', 'open', 'close', 'high', 'low', 'factor'])\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": [
" trade_date open close high low factor\n",
"0 2025-01-02 11.73 11.43 11.77 11.39 127.7841\n",
"1 2025-01-03 11.44 11.38 11.54 11.36 127.7841\n",
"2 2025-01-06 11.38 11.44 11.48 11.22 127.7841\n",
"3 2025-01-07 11.42 11.51 11.53 11.37 127.7841\n",
"4 2025-01-08 11.50 11.50 11.63 11.40 127.7841\n",
".. ... ... ... ... ... ...\n",
"183 2025-10-09 11.33 11.40 11.41 11.27 131.7878\n",
"184 2025-10-10 11.37 11.43 11.49 11.36 131.7878\n",
"185 2025-10-13 11.32 11.40 11.46 11.28 131.7878\n",
"186 2025-10-14 11.39 11.57 11.60 11.36 131.7878\n",
"187 2025-10-15 11.34 11.40 11.42 11.26 134.5794\n",
"\n",
"[188 rows x 6 columns]"
],
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>trade_date</th>\n",
" <th>open</th>\n",
" <th>close</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>factor</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-01-02</td>\n",
" <td>11.73</td>\n",
" <td>11.43</td>\n",
" <td>11.77</td>\n",
" <td>11.39</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-01-03</td>\n",
" <td>11.44</td>\n",
" <td>11.38</td>\n",
" <td>11.54</td>\n",
" <td>11.36</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2025-01-06</td>\n",
" <td>11.38</td>\n",
" <td>11.44</td>\n",
" <td>11.48</td>\n",
" <td>11.22</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2025-01-07</td>\n",
" <td>11.42</td>\n",
" <td>11.51</td>\n",
" <td>11.53</td>\n",
" <td>11.37</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2025-01-08</td>\n",
" <td>11.50</td>\n",
" <td>11.50</td>\n",
" <td>11.63</td>\n",
" <td>11.40</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>183</th>\n",
" <td>2025-10-09</td>\n",
" <td>11.33</td>\n",
" <td>11.40</td>\n",
" <td>11.41</td>\n",
" <td>11.27</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>184</th>\n",
" <td>2025-10-10</td>\n",
" <td>11.37</td>\n",
" <td>11.43</td>\n",
" <td>11.49</td>\n",
" <td>11.36</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>185</th>\n",
" <td>2025-10-13</td>\n",
" <td>11.32</td>\n",
" <td>11.40</td>\n",
" <td>11.46</td>\n",
" <td>11.28</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>186</th>\n",
" <td>2025-10-14</td>\n",
" <td>11.39</td>\n",
" <td>11.57</td>\n",
" <td>11.60</td>\n",
" <td>11.36</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>187</th>\n",
" <td>2025-10-15</td>\n",
" <td>11.34</td>\n",
" <td>11.40</td>\n",
" <td>11.42</td>\n",
" <td>11.26</td>\n",
" <td>134.5794</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>188 rows × 6 columns</p>\n",
"</div>"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 3
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2026-01-19T10:01:46.133661Z",
"start_time": "2026-01-19T10:01:46.044719Z"
}
},
"cell_type": "code",
"source": [
"dailies_df['factor'] = dailies_df['factor'].fillna(1.0)\n",
"dailies_df['open'] = dailies_df['open'] * dailies_df['factor']\n",
"dailies_df['close'] = dailies_df['close'] * dailies_df['factor']\n",
"dailies_df['high'] = dailies_df['high'] * dailies_df['factor']\n",
"dailies_df['low'] = dailies_df['low'] * dailies_df['factor']\n",
"dailies_df"
],
"id": "29226cf1c6fe9f94",
"outputs": [
{
"data": {
"text/plain": [
" trade_date open close high low \\\n",
"0 2025-01-02 191536.544976 186637.912112 192189.696025 185984.761064 \n",
"1 2025-01-03 186801.199875 185821.473302 188434.077496 185494.897778 \n",
"2 2025-01-06 185821.473302 186801.199875 187454.350923 183208.869108 \n",
"3 2025-01-07 186474.624350 187944.214209 188270.789734 185658.185540 \n",
"4 2025-01-08 187780.926447 187780.926447 189903.667355 186148.048826 \n",
".. ... ... ... ... ... \n",
"183 2025-10-09 196779.714513 197995.476209 198169.156451 195737.633059 \n",
"184 2025-10-10 197474.435482 198516.516936 199558.598389 197300.755240 \n",
"185 2025-10-13 196606.034270 197995.476209 199037.557663 195911.313301 \n",
"186 2025-10-14 197821.795966 200948.040328 201469.081055 197300.755240 \n",
"187 2025-10-15 205385.713015 206472.409910 206834.642208 203936.783823 \n",
" 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",
"0 127.7841 \n",
"1 127.7841 \n",
"2 127.7841 \n",
"3 127.7841 \n",
"4 127.7841 \n",
".. ... \n",
"183 131.7878 \n",
"184 131.7878 \n",
"185 131.7878 \n",
"186 131.7878 \n",
"187 134.5794 \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]"
],
@@ -280,58 +278,67 @@
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>trade_date</th>\n",
" <th>open</th>\n",
" <th>close</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>Open</th>\n",
" <th>Close</th>\n",
" <th>High</th>\n",
" <th>Low</th>\n",
" <th>Volume</th>\n",
" <th>factor</th>\n",
" </tr>\n",
" <tr>\n",
" <th>trade_date</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>2025-01-02</td>\n",
" <td>191536.544976</td>\n",
" <td>186637.912112</td>\n",
" <td>192189.696025</td>\n",
" <td>185984.761064</td>\n",
" <th>2025-01-02</th>\n",
" <td>1498.907493</td>\n",
" <td>1460.572263</td>\n",
" <td>1504.018857</td>\n",
" <td>1455.460899</td>\n",
" <td>1819596.99</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2025-01-03</td>\n",
" <td>186801.199875</td>\n",
" <td>185821.473302</td>\n",
" <td>188434.077496</td>\n",
" <td>185494.897778</td>\n",
" <th>2025-01-03</th>\n",
" <td>1461.850104</td>\n",
" <td>1454.183058</td>\n",
" <td>1474.628514</td>\n",
" <td>1451.627376</td>\n",
" <td>1154680.44</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2025-01-06</td>\n",
" <td>185821.473302</td>\n",
" <td>186801.199875</td>\n",
" <td>187454.350923</td>\n",
" <td>183208.869108</td>\n",
" <th>2025-01-06</th>\n",
" <td>1454.183058</td>\n",
" <td>1461.850104</td>\n",
" <td>1466.961468</td>\n",
" <td>1433.737602</td>\n",
" <td>1085536.30</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2025-01-07</td>\n",
" <td>186474.624350</td>\n",
" <td>187944.214209</td>\n",
" <td>188270.789734</td>\n",
" <td>185658.185540</td>\n",
" <th>2025-01-07</th>\n",
" <td>1459.294422</td>\n",
" <td>1470.794991</td>\n",
" <td>1473.350673</td>\n",
" <td>1452.905217</td>\n",
" <td>747862.88</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2025-01-08</td>\n",
" <td>187780.926447</td>\n",
" <td>187780.926447</td>\n",
" <td>189903.667355</td>\n",
" <td>186148.048826</td>\n",
" <th>2025-01-08</th>\n",
" <td>1469.517150</td>\n",
" <td>1469.517150</td>\n",
" <td>1486.129083</td>\n",
" <td>1456.738740</td>\n",
" <td>1062386.01</td>\n",
" <td>127.7841</td>\n",
" </tr>\n",
" <tr>\n",
@@ -344,48 +351,48 @@
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>183</th>\n",
" <td>2025-10-09</td>\n",
" <td>196779.714513</td>\n",
" <td>197995.476209</td>\n",
" <td>198169.156451</td>\n",
" <td>195737.633059</td>\n",
" <th>2025-10-09</th>\n",
" <td>1493.155774</td>\n",
" <td>1502.380920</td>\n",
" <td>1503.698798</td>\n",
" <td>1485.248506</td>\n",
" <td>1047469.06</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>184</th>\n",
" <td>2025-10-10</td>\n",
" <td>197474.435482</td>\n",
" <td>198516.516936</td>\n",
" <td>199558.598389</td>\n",
" <td>197300.755240</td>\n",
" <th>2025-10-10</th>\n",
" <td>1498.427286</td>\n",
" <td>1506.334554</td>\n",
" <td>1514.241822</td>\n",
" <td>1497.109408</td>\n",
" <td>1087947.75</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>185</th>\n",
" <td>2025-10-13</td>\n",
" <td>196606.034270</td>\n",
" <td>197995.476209</td>\n",
" <td>199037.557663</td>\n",
" <td>195911.313301</td>\n",
" <th>2025-10-13</th>\n",
" <td>1491.837896</td>\n",
" <td>1502.380920</td>\n",
" <td>1510.288188</td>\n",
" <td>1486.566384</td>\n",
" <td>1168801.73</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>186</th>\n",
" <td>2025-10-14</td>\n",
" <td>197821.795966</td>\n",
" <td>200948.040328</td>\n",
" <td>201469.081055</td>\n",
" <td>197300.755240</td>\n",
" <th>2025-10-14</th>\n",
" <td>1501.063042</td>\n",
" <td>1524.784846</td>\n",
" <td>1528.738480</td>\n",
" <td>1497.109408</td>\n",
" <td>1843428.36</td>\n",
" <td>131.7878</td>\n",
" </tr>\n",
" <tr>\n",
" <th>187</th>\n",
" <td>2025-10-15</td>\n",
" <td>205385.713015</td>\n",
" <td>206472.409910</td>\n",
" <td>206834.642208</td>\n",
" <td>203936.783823</td>\n",
" <th>2025-10-15</th>\n",
" <td>1526.130396</td>\n",
" <td>1534.205160</td>\n",
" <td>1536.896748</td>\n",
" <td>1515.364044</td>\n",
" <td>1271061.03</td>\n",
" <td>134.5794</td>\n",
" </tr>\n",
" </tbody>\n",
@@ -394,12 +401,303 @@
"</div>"
]
},
"execution_count": 5,
"execution_count": 88,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 5
"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": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Open</th>\n",
" <th>Close</th>\n",
" <th>High</th>\n",
" <th>Low</th>\n",
" <th>Volume</th>\n",
" <th>factor</th>\n",
" <th>sma30</th>\n",
" <th>sma60</th>\n",
" </tr>\n",
" <tr>\n",
" <th>trade_date</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2025-10-09</th>\n",
" <td>1493.155774</td>\n",
" <td>1502.380920</td>\n",
" <td>1503.698798</td>\n",
" <td>1485.248506</td>\n",
" <td>1047469.06</td>\n",
" <td>131.7878</td>\n",
" <td>1504.094161</td>\n",
" <td>1546.925196</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2025-10-10</th>\n",
" <td>1498.427286</td>\n",
" <td>1506.334554</td>\n",
" <td>1514.241822</td>\n",
" <td>1497.109408</td>\n",
" <td>1087947.75</td>\n",
" <td>131.7878</td>\n",
" <td>1504.357737</td>\n",
" <td>1543.762289</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2025-10-13</th>\n",
" <td>1491.837896</td>\n",
" <td>1502.380920</td>\n",
" <td>1510.288188</td>\n",
" <td>1486.566384</td>\n",
" <td>1168801.73</td>\n",
" <td>131.7878</td>\n",
" <td>1503.698798</td>\n",
" <td>1540.862958</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2025-10-14</th>\n",
" <td>1501.063042</td>\n",
" <td>1524.784846</td>\n",
" <td>1528.738480</td>\n",
" <td>1497.109408</td>\n",
" <td>1843428.36</td>\n",
" <td>131.7878</td>\n",
" <td>1506.202766</td>\n",
" <td>1536.997182</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2025-10-15</th>\n",
" <td>1526.130396</td>\n",
" <td>1534.205160</td>\n",
" <td>1536.896748</td>\n",
" <td>1515.364044</td>\n",
" <td>1271061.03</td>\n",
" <td>134.5794</td>\n",
" <td>1507.803737</td>\n",
" <td>1533.840781</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
]
},
"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": {

126
note.md Normal file
View File

@@ -0,0 +1,126 @@
# 基础时间与权益指标
## Exposure Time [%] - 持仓时间占比(%
衡量策略在统计周期内实际持有头寸的时间占总时间的百分比。反映策略的“活跃度”如占比100%=全程持仓,占比低=多数时间空仓),辅助判断交易频率和资金使用效率。
## Equity Final [$] - 最终权益
策略运行结束时的账户总资金(本金+盈亏),是最基础的收益结果指标,直接体现最终资金规模。
## Equity Peak [$] - 权益峰值
统计周期内账户权益的最大值。对比最终权益可判断策略是否从峰值回落,结合回撤指标能评估收益稳定性。
# 收益率类指标(核心收益衡量)
## Return [%] - 总收益率(%
周期内总收益占初始本金的百分比(`(最终权益-初始本金)/初始本金×100%`),直观反映整体盈利/亏损程度,但未考虑时间因素。
## Buy & Hold Return [%] - 买入并持有收益率(%
作为“基准收益率”,模拟“买入标的后长期持有不操作”的收益。用于对比策略收益,判断策略是否跑赢简单持有,是评估策略有效性的核心参照。
## Return (Ann.) [%] - 年化收益率(%
将周期总收益折算为按年计算的收益(`(1+总收益率)^(365/持仓天数) - 1`),消除时间周期差异,是跨周期对比不同策略收益的关键指标。
## CAGR [%] - 复合年均增长率(%
即“年均复合收益率”(`(最终权益/初始本金)^(1/年数) - 1`),衡量资金长期复利增长速度,更贴合多年期策略的收益评估,避免短期高收益误导。
# 风险类指标(衡量亏损与波动风险)
## Volatility (Ann.) [%] - 年化波动率(%
收益波动程度的年化标准差,反映收益稳定性。波动率越高,收益起伏越大,策略“震荡风险”越高;波动率低则收益更平稳。
## Max. Drawdown [%] - 最大回撤(%
权益从峰值回落至谷值的最大幅度(`(峰值-谷值)/峰值×100%`核心风险指标。比如最大回撤20%说明策略曾从最高点亏掉20%,直接体现抗风险能力。
## Avg. Drawdown [%] - 平均回撤(%
所有回撤的平均幅度。若最大回撤远高于平均回撤,说明策略曾出现极端亏损;两者接近则回撤风险更均匀。
## Max. Drawdown Duration - 最大回撤持续时长
最大回撤从峰值回落至恢复峰值的时间(天/月),反映策略从最大亏损中回血的速度,时长越长则恢复能力越弱。
## Avg. Drawdown Duration - 平均回撤持续时长
所有回撤周期的平均时间,辅助判断策略亏损后的恢复效率。
# 风险收益比指标(性价比核心)
## Sharpe Ratio - 夏普比率
衡量“每承担1单位风险的超额收益”`(年化收益率-无风险利率)/年化波动率`
无风险利率通常取国债利率3%左右)。比率越高性价比越高(>1较好>2优秀
## Sortino Ratio - 索提诺比率
改进版夏普比率,仅用“下行波动率”(亏损方向波动)计算风险,更贴合投资者对“亏损风险”的关注,适合评估稳健型策略。
## Calmar Ratio - 卡尔玛比率
`年化收益率/最大回撤(绝对值)`,直接反映“收益能否覆盖最大亏损”,比率越高,策略用小回撤换高收益的能力越强。
# 资产定价系数(市场相关性)
## Alpha [%] - 阿尔法系数(%
衡量策略“超额收益”超出市场基准的收益Alpha为正说明策略能跑赢市场反映主动管理能力为负则跑输市场。
## Beta - 贝塔系数
衡量策略与市场基准的波动同步性。Beta=1=和市场波动一致Beta>1=策略更激进波动更大Beta<1=策略更稳健Beta<0=与市场反向波动。
# 交易行为与质量指标
## Trades - 交易总次数
统计周期内总交易笔数,反映策略交易频率(高频/低频),结合胜率可判断策略有效性。
## Win Rate [%] - 胜率(%
盈利交易次数/总次数×100%,直观反映“赚钱交易的比例”,但需结合盈亏比(平均盈利/平均亏损使用如胜率50%+盈亏比3:1仍盈利
## Best Trade [%] - 最佳单笔交易收益率(%
单次盈利幅度最大值,反映策略盈利上限,但需警惕是否由偶然高收益拉高整体表现。
## Worst Trade [%] - 最差单笔交易收益率(%
单次亏损幅度最大值(通常为负),反映单笔交易的最大亏损风险。
## Avg. Trade [%] - 平均单笔交易收益率(%
所有交易收益率的平均值,反映单笔交易的平均盈利能力,为正则单笔交易平均赚钱。
## Max. Trade Duration - 单笔交易最长持有时长
单次持仓的最长时间,定义策略风格(日内/短线/中长线)。
## Avg. Trade Duration - 单笔交易平均持有时长
所有交易持仓时长的平均值,辅助判断资金周转效率。
# 综合绩效指标(策略可持续性)
## Profit Factor - 盈利因子
`总盈利金额/总亏损金额(绝对值)`,核心指标。>1说明总盈利>总亏损数值越高盈利能力越强如盈利因子2=每亏1元赚2元
## Expectancy [%] - 期望收益(%
每笔交易的预期收益(`胜率×平均盈利 - (1-胜率)×平均亏损`),为正则策略长期可盈利,数值越高预期收益越好。
## SQN - 系统质量数
衡量策略收益的“统计显著性”(`√交易次数 × 期望收益 / 交易收益标准差`。SQN>1.6合格,>2.5优秀,>3.0卓越,判断收益是否为偶然结果。
## Kelly Criterion - 凯利准则
计算“最优仓位比例”(`(胜率×(盈亏比+1)-1)/盈亏比`),确定每笔交易的最佳资金投入比例,最大化长期复利收益,同时控制破产风险(实际应用中通常减半使用)。

View File

@@ -5,8 +5,10 @@ description = "Stock analysis"
requires-python = ">=3.14"
dependencies = [
"backtesting~=0.6.5",
"duckdb>=1.4.3",
"jupyter~=1.1.1",
"matplotlib~=3.10.8",
"mplfinance>=0.12.10b0",
"pandas~=2.3.3",
"pandas-stubs~=2.3.3",
"peewee~=3.19.0",

72
sql2dataframe.ipynb Normal file
View File

@@ -0,0 +1,72 @@
{
"cells": [
{
"metadata": {},
"cell_type": "code",
"outputs": [],
"execution_count": null,
"source": [
"import pandas as pd\n",
"\n",
"host = '81.71.3.24'\n",
"port = 6785\n",
"database = 'leopard_dev'\n",
"username = 'leopard'\n",
"password = '9NEzFzovnddf@PyEP?e*AYAWnCyd7UhYwQK$pJf>7?ccFiN^x4$eKEZ5~E<7<+~X'"
],
"id": "1e8d815ee9b8c936"
},
{
"cell_type": "code",
"execution_count": null,
"id": "initial_id",
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import psycopg2\n",
"\n",
"dailies_df = pd.DataFrame()\n",
"\n",
"with psycopg2.connect(host=host, port=port, database=database, user=username, password=password) as connection:\n",
" with connection.cursor() as cursor:\n",
" # language=PostgreSQL\n",
" cursor.execute(\n",
" \"\"\"select trade_date, open, close, high, low, 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\"\"\"\n",
" )\n",
" rows = cursor.fetchall()\n",
"\n",
" dailies_df = pd.DataFrame.from_records(rows, columns=['trade_date', 'open', 'close', 'high', 'low', 'factor'])\n",
"\n",
"dailies_df"
]
}
],
"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
}

32
uv.lock generated
View File

@@ -338,6 +338,21 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" },
]
[[package]]
name = "duckdb"
version = "1.4.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7f/da/17c3eb5458af69d54dedc8d18e4a32ceaa8ce4d4c699d45d6d8287e790c3/duckdb-1.4.3.tar.gz", hash = "sha256:fea43e03604c713e25a25211ada87d30cd2a044d8f27afab5deba26ac49e5268", size = 18478418, upload-time = "2025-12-09T10:59:22.945Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b6/f4/a38651e478fa41eeb8e43a0a9c0d4cd8633adea856e3ac5ac95124b0fdbf/duckdb-1.4.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:316711a9e852bcfe1ed6241a5f654983f67e909e290495f3562cccdf43be8180", size = 29042272, upload-time = "2025-12-09T10:58:51.826Z" },
{ url = "https://files.pythonhosted.org/packages/16/de/2cf171a66098ce5aeeb7371511bd2b3d7b73a2090603b0b9df39f8aaf814/duckdb-1.4.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9e625b2b4d52bafa1fd0ebdb0990c3961dac8bb00e30d327185de95b68202131", size = 15419343, upload-time = "2025-12-09T10:58:54.439Z" },
{ url = "https://files.pythonhosted.org/packages/35/28/6b0a7830828d4e9a37420d87e80fe6171d2869a9d3d960bf5d7c3b8c7ee4/duckdb-1.4.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:130c6760f6c573f9c9fe9aba56adba0fab48811a4871b7b8fd667318b4a3e8da", size = 13748905, upload-time = "2025-12-09T10:58:56.656Z" },
{ url = "https://files.pythonhosted.org/packages/15/4d/778628e194d63967870873b9581c8a6b4626974aa4fbe09f32708a2d3d3a/duckdb-1.4.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c88effaa557a11267706b01419c542fe42f893dee66e5a6daa5974ea2d4a46", size = 18487261, upload-time = "2025-12-09T10:58:58.866Z" },
{ url = "https://files.pythonhosted.org/packages/c6/5f/87e43af2e4a0135f9675449563e7c2f9b6f1fe6a2d1691c96b091f3904dd/duckdb-1.4.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1b35491db98ccd11d151165497c084a9d29d3dc42fc80abea2715a6c861ca43d", size = 20497138, upload-time = "2025-12-09T10:59:01.241Z" },
{ url = "https://files.pythonhosted.org/packages/94/41/abec537cc7c519121a2a83b9a6f180af8915fabb433777dc147744513e74/duckdb-1.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:23b12854032c1a58d0452e2b212afa908d4ce64171862f3792ba9a596ba7c765", size = 12836056, upload-time = "2025-12-09T10:59:03.388Z" },
{ url = "https://files.pythonhosted.org/packages/b1/5a/8af5b96ce5622b6168854f479ce846cf7fb589813dcc7d8724233c37ded3/duckdb-1.4.3-cp314-cp314-win_arm64.whl", hash = "sha256:90f241f25cffe7241bf9f376754a5845c74775e00e1c5731119dc88cd71e0cb2", size = 13527759, upload-time = "2025-12-09T10:59:05.496Z" },
]
[[package]]
name = "executing"
version = "2.2.1"
@@ -850,8 +865,10 @@ version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "backtesting" },
{ name = "duckdb" },
{ name = "jupyter" },
{ name = "matplotlib" },
{ name = "mplfinance" },
{ name = "pandas" },
{ name = "pandas-stubs" },
{ name = "peewee" },
@@ -861,8 +878,10 @@ dependencies = [
[package.metadata]
requires-dist = [
{ name = "backtesting", specifier = "~=0.6.5" },
{ name = "duckdb", specifier = ">=1.4.3" },
{ name = "jupyter", specifier = "~=1.1.1" },
{ name = "matplotlib", specifier = "~=3.10.8" },
{ name = "mplfinance", specifier = ">=0.12.10b0" },
{ name = "pandas", specifier = "~=2.3.3" },
{ name = "pandas-stubs", specifier = "~=2.3.3" },
{ name = "peewee", specifier = "~=3.19.0" },
@@ -953,6 +972,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" },
]
[[package]]
name = "mplfinance"
version = "0.12.10b0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "matplotlib" },
{ name = "pandas" },
]
sdist = { url = "https://files.pythonhosted.org/packages/6c/a9/34e7998d02fb58fae04f750444ce4e95e75f3a08dad17fb2d32098a97834/mplfinance-0.12.10b0.tar.gz", hash = "sha256:7da150b5851aa5119ad6e06b55e48338b619bb6773f1b85df5de67a5ffd917bf", size = 70117, upload-time = "2023-08-02T15:13:53.829Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d7/d9/31c436ea7673c21a5bf3fc747bc7f63377582dfe845c3004d3e46f9deee0/mplfinance-0.12.10b0-py3-none-any.whl", hash = "sha256:76d3b095f05ff35de730751649de063bea4064d0c49b21b6182c82997a7f52bb", size = 75016, upload-time = "2023-08-02T15:13:52.022Z" },
]
[[package]]
name = "narwhals"
version = "2.15.0"