Skip to content

Instantly share code, notes, and snippets.

@nagishin
Created February 17, 2023 17:24
Show Gist options
  • Save nagishin/3cc9348347bc3cae5bb86354dea3bba9 to your computer and use it in GitHub Desktop.
Save nagishin/3cc9348347bc3cae5bb86354dea3bba9 to your computer and use it in GitHub Desktop.
polars_backtest.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"toc_visible": true,
"authorship_tag": "ABX9TyNw5VBD4foz8oG3Jl8jpIs6",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/nagishin/3cc9348347bc3cae5bb86354dea3bba9/polars_backtest.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"---\n",
"# 【DataFrameで高速バックテスト(pandas vs polars)】\n",
"* このnotebookは下記noteで解説されているバックテストをベースにpandasとpolarsのパフォーマンス比較を行っています。\n",
"* ロジックやpandasでの詳細な解説はnoteに記載されているため、本コードを参照する前に一読することをおすすめします。\n",
"\n",
"<b>[参考]</b><br>\n",
"くもすけさん著<br>\n",
"[pandasを用いた超高速バックテスト](https://note.com/kunmosky1/n/nc15678b3dcc2)\n",
"<br><br>\n",
"<b>[注意]</b><br>\n",
"このnotebookはpandasとpolarsのコーディングやパフォーマンス比較を目的としています。<br>\n",
"バックテストのロジック内容や評価方法は一例としてお考えください。\n",
"\n",
"---"
],
"metadata": {
"id": "1BEKAMEhOzCW"
}
},
{
"cell_type": "markdown",
"source": [
"## 【polarsインストール】"
],
"metadata": {
"id": "GzpivxK2Finy"
}
},
{
"cell_type": "code",
"source": [
"!pip install polars"
],
"metadata": {
"id": "nWC3SbV2XPMu"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### 各種バージョン"
],
"metadata": {
"id": "6qw9YYrM3n5i"
}
},
{
"cell_type": "code",
"source": [
"import os\n",
"import time\n",
"from datetime import datetime\n",
"import pandas as pd\n",
"import polars as pl\n",
"\n",
"!python --version\n",
"print('pandas', pd.__version__)\n",
"print('polars', pl.__version__)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "TKDre2BA1DCc",
"outputId": "6c1f53fc-53a5-4802-dd57-5b11accce477"
},
"execution_count": 24,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Python 3.8.10\n",
"pandas 1.3.5\n",
"polars 0.16.6\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"## 【初期設定】\n",
"\n",
"<b>ロジック</b><br>\n",
"* 長期SMAが上がっていて、短期SMAが長期SMAを超えた時にロング\n",
"* 長期SMAが下がっていて、短期SMAが長期SMAを下抜けした時にショート\n",
"* 同方向のエントリーが連続した場合はポジションを積み増し(ピラミッディング)\n",
"* 逆方向のエントリーでドテン"
],
"metadata": {
"id": "a74yTXcRFojC"
}
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"id": "ott94-XvRyj8"
},
"outputs": [],
"source": [
"SYMBOL = 'BTCUSDT' # 通貨ペア\n",
"PERIOD = '5m' # 時間足\n",
"YEAR = 2022 # 対象年\n",
"\n",
"SHORT_SMA = 20 # 短期 移動平均期間\n",
"LONG_SMA = 47 # 長期 移動平均期間\n",
"PYRAMIDING = 4 # ピラミッディング回数\n",
"COMMISION = 0.075 # taker手数料%\n",
"\n",
"CSV_PATH = f'./ohlcv_{SYMBOL}_{YEAR}_{PERIOD}.csv' # CSVパス(取得したOHLCV保存)\n",
"\n",
"NANOSECONDS = 1_000_000_000 # nano秒単位"
]
},
{
"cell_type": "markdown",
"source": [
"## 【OHLCV取得 & CSV保存】\n",
"<b>対象データ</b>\n",
"* OHLCVデータ : Binance 5m OHLCV\n",
"\n",
"<b>対象期間</b>\n",
"* 2022-01-01 ~ 2022-12-31"
],
"metadata": {
"id": "0gqut-tpF7LB"
}
},
{
"cell_type": "code",
"source": [
"# ファイル存在チェック\n",
"df_ohlcv_base = None\n",
"if os.path.isfile(CSV_PATH):\n",
" # ローカルCSV読み込み\n",
" df_ohlcv_base = pd.read_csv(CSV_PATH)\n",
"else:\n",
" # csvをDataFrameに読み込み\n",
" for month in range(1,13):\n",
" df = pd.read_csv(f'https://data.binance.vision/data/spot/monthly/klines/{SYMBOL}/{PERIOD}/{SYMBOL}-{PERIOD}-{YEAR}-{month:02}.zip',\n",
" usecols=[0,1,2,3,4,5],\n",
" names=['timestamp', 'open', 'high', 'low', 'close', 'volume'],\n",
" dtype={'timestamp':'int', 'open':'float', 'high':'float', 'low':'float', 'close':'float', 'volume':'float'})\n",
" if df is not None and len(df.index) > 0:\n",
" if df_ohlcv_base is None:\n",
" df_ohlcv_base = df\n",
" else:\n",
" df_ohlcv_base = pd.concat([df_ohlcv_base, df])\n",
" # UnixTime(timestamp)順ソート\n",
" df_ohlcv_base.sort_values(by='timestamp', ascending=True, inplace=True)\n",
" df_ohlcv_base.reset_index(drop=True, inplace=True)\n",
" df_ohlcv_base['timestamp'] = (df_ohlcv_base['timestamp'] / 1000).astype(int) # ms->s\n",
" # ローカルに保存\n",
" df_ohlcv_base.to_csv(CSV_PATH, header=True, index=False)\n",
"\n",
"display(df_ohlcv_base)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 424
},
"id": "8i83tLdXFvva",
"outputId": "2d523e8d-7146-4d32-c1e0-dbedfef6f8c4"
},
"execution_count": 26,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
" timestamp open high low close volume\n",
"0 1640995200 46216.93 46391.49 46208.37 46321.34 185.67558\n",
"1 1640995500 46321.34 46527.26 46280.00 46371.11 123.43577\n",
"2 1640995800 46369.79 46394.00 46276.22 46332.51 77.54574\n",
"3 1640996100 46332.52 46332.52 46236.27 46293.90 101.14315\n",
"4 1640996400 46295.42 46421.27 46286.25 46395.53 135.32479\n",
"... ... ... ... ... ... ...\n",
"105115 1672529700 16538.17 16551.24 16536.84 16545.68 501.06148\n",
"105116 1672530000 16545.68 16550.26 16543.45 16546.13 277.70571\n",
"105117 1672530300 16546.14 16550.55 16536.62 16539.05 292.41232\n",
"105118 1672530600 16538.39 16541.26 16534.92 16540.42 180.18579\n",
"105119 1672530900 16540.42 16544.47 16535.05 16542.40 227.06684\n",
"\n",
"[105120 rows x 6 columns]"
],
"text/html": [
"\n",
" <div id=\"df-efc288c4-612a-4708-934a-789eec15a15c\">\n",
" <div class=\"colab-df-container\">\n",
" <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>timestamp</th>\n",
" <th>open</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>close</th>\n",
" <th>volume</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1640995200</td>\n",
" <td>46216.93</td>\n",
" <td>46391.49</td>\n",
" <td>46208.37</td>\n",
" <td>46321.34</td>\n",
" <td>185.67558</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1640995500</td>\n",
" <td>46321.34</td>\n",
" <td>46527.26</td>\n",
" <td>46280.00</td>\n",
" <td>46371.11</td>\n",
" <td>123.43577</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1640995800</td>\n",
" <td>46369.79</td>\n",
" <td>46394.00</td>\n",
" <td>46276.22</td>\n",
" <td>46332.51</td>\n",
" <td>77.54574</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1640996100</td>\n",
" <td>46332.52</td>\n",
" <td>46332.52</td>\n",
" <td>46236.27</td>\n",
" <td>46293.90</td>\n",
" <td>101.14315</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1640996400</td>\n",
" <td>46295.42</td>\n",
" <td>46421.27</td>\n",
" <td>46286.25</td>\n",
" <td>46395.53</td>\n",
" <td>135.32479</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>105115</th>\n",
" <td>1672529700</td>\n",
" <td>16538.17</td>\n",
" <td>16551.24</td>\n",
" <td>16536.84</td>\n",
" <td>16545.68</td>\n",
" <td>501.06148</td>\n",
" </tr>\n",
" <tr>\n",
" <th>105116</th>\n",
" <td>1672530000</td>\n",
" <td>16545.68</td>\n",
" <td>16550.26</td>\n",
" <td>16543.45</td>\n",
" <td>16546.13</td>\n",
" <td>277.70571</td>\n",
" </tr>\n",
" <tr>\n",
" <th>105117</th>\n",
" <td>1672530300</td>\n",
" <td>16546.14</td>\n",
" <td>16550.55</td>\n",
" <td>16536.62</td>\n",
" <td>16539.05</td>\n",
" <td>292.41232</td>\n",
" </tr>\n",
" <tr>\n",
" <th>105118</th>\n",
" <td>1672530600</td>\n",
" <td>16538.39</td>\n",
" <td>16541.26</td>\n",
" <td>16534.92</td>\n",
" <td>16540.42</td>\n",
" <td>180.18579</td>\n",
" </tr>\n",
" <tr>\n",
" <th>105119</th>\n",
" <td>1672530900</td>\n",
" <td>16540.42</td>\n",
" <td>16544.47</td>\n",
" <td>16535.05</td>\n",
" <td>16542.40</td>\n",
" <td>227.06684</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>105120 rows × 6 columns</p>\n",
"</div>\n",
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-efc288c4-612a-4708-934a-789eec15a15c')\"\n",
" title=\"Convert this dataframe to an interactive table.\"\n",
" style=\"display:none;\">\n",
" \n",
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
" width=\"24px\">\n",
" <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
" <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
" </svg>\n",
" </button>\n",
" \n",
" <style>\n",
" .colab-df-container {\n",
" display:flex;\n",
" flex-wrap:wrap;\n",
" gap: 12px;\n",
" }\n",
"\n",
" .colab-df-convert {\n",
" background-color: #E8F0FE;\n",
" border: none;\n",
" border-radius: 50%;\n",
" cursor: pointer;\n",
" display: none;\n",
" fill: #1967D2;\n",
" height: 32px;\n",
" padding: 0 0 0 0;\n",
" width: 32px;\n",
" }\n",
"\n",
" .colab-df-convert:hover {\n",
" background-color: #E2EBFA;\n",
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
" fill: #174EA6;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert {\n",
" background-color: #3B4455;\n",
" fill: #D2E3FC;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert:hover {\n",
" background-color: #434B5C;\n",
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
" fill: #FFFFFF;\n",
" }\n",
" </style>\n",
"\n",
" <script>\n",
" const buttonEl =\n",
" document.querySelector('#df-efc288c4-612a-4708-934a-789eec15a15c button.colab-df-convert');\n",
" buttonEl.style.display =\n",
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
"\n",
" async function convertToInteractive(key) {\n",
" const element = document.querySelector('#df-efc288c4-612a-4708-934a-789eec15a15c');\n",
" const dataTable =\n",
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
" [key], {});\n",
" if (!dataTable) return;\n",
"\n",
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
" + ' to learn more about interactive tables.';\n",
" element.innerHTML = '';\n",
" dataTable['output_type'] = 'display_data';\n",
" await google.colab.output.renderOutput(dataTable, element);\n",
" const docLink = document.createElement('div');\n",
" docLink.innerHTML = docLinkHtml;\n",
" element.appendChild(docLink);\n",
" }\n",
" </script>\n",
" </div>\n",
" </div>\n",
" "
]
},
"metadata": {}
}
]
},
{
"cell_type": "markdown",
"source": [
"## 【バックテスト】"
],
"metadata": {
"id": "pBaWX2fGGS2h"
}
},
{
"cell_type": "markdown",
"source": [
"### pandas"
],
"metadata": {
"id": "N-JKYYucGXUh"
}
},
{
"cell_type": "markdown",
"source": [
"#### CSV読み込み"
],
"metadata": {
"id": "4ag9sF2sJcZN"
}
},
{
"cell_type": "code",
"source": [
"s = time.time()\n",
"\n",
"# csvをDataFrameに読み込み\n",
"df_ohlcv_pd = pd.read_csv(CSV_PATH)\n",
"\n",
"ret = round((time.time() - s) * 1000, 3)\n",
"print(f'[処理時間]: {ret} ms\\n')"
],
"metadata": {
"id": "Z87Xv3pMRJRD",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "58032fe7-bf19-4e67-faa1-43061e9aaba0"
},
"execution_count": 27,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[処理時間]: 103.784 ms\n",
"\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"#### バックテスト関数\n",
"このコードの詳細な解説は下記noteを参照してください。<br>\n",
"\n",
"くもすけさん著<br>\n",
"[pandasを用いた超高速バックテスト](https://note.com/kunmosky1/n/nc15678b3dcc2)"
],
"metadata": {
"id": "jLKJFD7vJqlp"
}
},
{
"cell_type": "code",
"source": [
"def backtest_pandas(short_sma:int, long_sma:int, pyramid:int, df_ohlcv:pd.DataFrame=None) -> pd.DataFrame:\n",
" \"\"\"**【バックテスト(pandas)】**\n",
"\n",
" 短期/長期移動平均のゴールデンクロス/デッドクロスでエントリー \n",
" 同方向に注文が重なった場合は指定回数まで積み増し\n",
"\n",
" :param short_sma: 短期 移動平均期間\n",
" :param long_sma: 長期 移動平均期間\n",
" :param pyramid: 積み増し回数\n",
" :param df_ohlcv: OHLCV DataFrame(pandas)\n",
"\n",
" :return: 処理結果 DataFrame\n",
" \"\"\"\n",
" global df_ohlcv_pd\n",
"\n",
" if df_ohlcv is None:\n",
" df = df_ohlcv_pd.copy()\n",
" else:\n",
" df = df_ohlcv.copy()\n",
"\n",
" # UnixTime(timestamp)からdatetime列生成\n",
" df['datetime'] = pd.to_datetime(df['timestamp'], unit='s', utc=True)\n",
" # datetimeをindexに設定\n",
" df.set_index('datetime', inplace=True)\n",
"\n",
" # SMA計算\n",
" df['short_sma'] = df['close'].rolling(short_sma, min_periods=1).mean()\n",
" df['long_sma'] = df['close'].rolling(long_sma, min_periods=1).mean()\n",
"\n",
" # エントリー判定\n",
" def crossover(x, y):\n",
" return ((x - y) > 0) & ((x.shift(1) - y) < 0)\n",
" def crossunder(x, y):\n",
" return ((x - y) < 0) & ((x.shift(1) - y) > 0)\n",
" df['long'] = (df['long_sma'].diff(1) > 0) & crossover(df['long_sma'], df['short_sma'])\n",
" df['short'] = (df['long_sma'].diff(1) < 0) & crossunder(df['long_sma'], df['short_sma'])\n",
"\n",
" # ポジション計算(ドテン&ピラミッディング)\n",
" df['order'] = 0\n",
" df['order'] = df['order'].where(df['long'] != True, 1)\n",
" df['order'] = df['order'].where(df['short'] != True, -1)\n",
" df['pos'] = df['order'].where(df['order'] != 0,).fillna(method='ffill').fillna(0)\n",
" df['pos'] = df.groupby((df['pos'] * df['pos'].shift(1) < 0).cumsum().fillna(0))['order'].cumsum()\n",
" df['pos'] = df['pos'].where(df['pos'] <= pyramid, pyramid) \n",
" df['pos'] = df['pos'].where(df['pos'] >= -pyramid, -pyramid)\n",
" df['pos'] /= pyramid\n",
"\n",
" # 損益計算\n",
" df['return']= -df['open'].diff(-1)\n",
" df['commision'] = df['open'].shift(-1) * COMMISION / 100 * abs(df['pos'] - df['pos'].shift(1))\n",
" df['profit'] = df['return'] * df['pos'].shift(1) - df['commision']\n",
" df['pnl'] = df['profit'].cumsum()\n",
" df['pnl'] = df['pnl'].fillna(method='ffill')\n",
"\n",
" return df"
],
"metadata": {
"id": "1Fks-_RfHmDK"
},
"execution_count": 28,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"#### バックテスト実行"
],
"metadata": {
"id": "hCeRoPc2J1qz"
}
},
{
"cell_type": "code",
"source": [
"s = time.time()\n",
"\n",
"# バックテスト\n",
"df_result_pd = backtest_pandas(SHORT_SMA, LONG_SMA, PYRAMIDING, df_ohlcv_pd)\n",
"\n",
"ret = round((time.time() - s) * 1000, 3)\n",
"print(f'[処理時間]: {ret} ms\\n')\n",
"\n",
"# 結果表示\n",
"display(df_result_pd)\n",
"# 結果表示(ポジション変化が有ったところだけ)\n",
"#display(df_result_pd[df_result_pd['pos'].diff(1) != 0][['open','long','short','pos','pnl']])"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 707
},
"id": "USKdfuYnS9B-",
"outputId": "2ec28e43-1a89-40e2-be3b-42d1d8c1cd03"
},
"execution_count": 44,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[処理時間]: 76.425 ms\n",
"\n"
]
},
{
"output_type": "display_data",
"data": {
"text/plain": [
" timestamp open high low close \\\n",
"datetime \n",
"2022-01-01 00:00:00+00:00 1640995200 46216.93 46391.49 46208.37 46321.34 \n",
"2022-01-01 00:05:00+00:00 1640995500 46321.34 46527.26 46280.00 46371.11 \n",
"2022-01-01 00:10:00+00:00 1640995800 46369.79 46394.00 46276.22 46332.51 \n",
"2022-01-01 00:15:00+00:00 1640996100 46332.52 46332.52 46236.27 46293.90 \n",
"2022-01-01 00:20:00+00:00 1640996400 46295.42 46421.27 46286.25 46395.53 \n",
"... ... ... ... ... ... \n",
"2022-12-31 23:35:00+00:00 1672529700 16538.17 16551.24 16536.84 16545.68 \n",
"2022-12-31 23:40:00+00:00 1672530000 16545.68 16550.26 16543.45 16546.13 \n",
"2022-12-31 23:45:00+00:00 1672530300 16546.14 16550.55 16536.62 16539.05 \n",
"2022-12-31 23:50:00+00:00 1672530600 16538.39 16541.26 16534.92 16540.42 \n",
"2022-12-31 23:55:00+00:00 1672530900 16540.42 16544.47 16535.05 16542.40 \n",
"\n",
" volume short_sma long_sma long \\\n",
"datetime \n",
"2022-01-01 00:00:00+00:00 185.67558 46321.340000 46321.340000 False \n",
"2022-01-01 00:05:00+00:00 123.43577 46346.225000 46346.225000 False \n",
"2022-01-01 00:10:00+00:00 77.54574 46341.653333 46341.653333 False \n",
"2022-01-01 00:15:00+00:00 101.14315 46329.715000 46329.715000 False \n",
"2022-01-01 00:20:00+00:00 135.32479 46342.878000 46342.878000 False \n",
"... ... ... ... ... \n",
"2022-12-31 23:35:00+00:00 501.06148 16530.430500 16551.263404 False \n",
"2022-12-31 23:40:00+00:00 277.70571 16530.540000 16550.433191 False \n",
"2022-12-31 23:45:00+00:00 292.41232 16529.683500 16549.552553 False \n",
"2022-12-31 23:50:00+00:00 180.18579 16528.435500 16548.920213 False \n",
"2022-12-31 23:55:00+00:00 227.06684 16528.974500 16548.307660 False \n",
"\n",
" short order pos return commision profit \\\n",
"datetime \n",
"2022-01-01 00:00:00+00:00 False 0 0.0 104.41 NaN NaN \n",
"2022-01-01 00:05:00+00:00 False 0 0.0 48.45 0.0 0.000 \n",
"2022-01-01 00:10:00+00:00 False 0 0.0 -37.27 0.0 -0.000 \n",
"2022-01-01 00:15:00+00:00 False 0 0.0 -37.10 0.0 -0.000 \n",
"2022-01-01 00:20:00+00:00 False 0 0.0 100.11 0.0 0.000 \n",
"... ... ... ... ... ... ... \n",
"2022-12-31 23:35:00+00:00 False 0 0.5 7.51 0.0 3.755 \n",
"2022-12-31 23:40:00+00:00 False 0 0.5 0.46 0.0 0.230 \n",
"2022-12-31 23:45:00+00:00 False 0 0.5 -7.75 0.0 -3.875 \n",
"2022-12-31 23:50:00+00:00 False 0 0.5 2.03 0.0 1.015 \n",
"2022-12-31 23:55:00+00:00 False 0 0.5 NaN NaN NaN \n",
"\n",
" pnl \n",
"datetime \n",
"2022-01-01 00:00:00+00:00 NaN \n",
"2022-01-01 00:05:00+00:00 0.000000 \n",
"2022-01-01 00:10:00+00:00 0.000000 \n",
"2022-01-01 00:15:00+00:00 0.000000 \n",
"2022-01-01 00:20:00+00:00 0.000000 \n",
"... ... \n",
"2022-12-31 23:35:00+00:00 7148.928371 \n",
"2022-12-31 23:40:00+00:00 7149.158371 \n",
"2022-12-31 23:45:00+00:00 7145.283371 \n",
"2022-12-31 23:50:00+00:00 7146.298371 \n",
"2022-12-31 23:55:00+00:00 7146.298371 \n",
"\n",
"[105120 rows x 16 columns]"
],
"text/html": [
"\n",
" <div id=\"df-92a90e67-7959-43b7-8195-b1602f4ab13a\">\n",
" <div class=\"colab-df-container\">\n",
" <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>timestamp</th>\n",
" <th>open</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>close</th>\n",
" <th>volume</th>\n",
" <th>short_sma</th>\n",
" <th>long_sma</th>\n",
" <th>long</th>\n",
" <th>short</th>\n",
" <th>order</th>\n",
" <th>pos</th>\n",
" <th>return</th>\n",
" <th>commision</th>\n",
" <th>profit</th>\n",
" <th>pnl</th>\n",
" </tr>\n",
" <tr>\n",
" <th>datetime</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",
" <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>2022-01-01 00:00:00+00:00</th>\n",
" <td>1640995200</td>\n",
" <td>46216.93</td>\n",
" <td>46391.49</td>\n",
" <td>46208.37</td>\n",
" <td>46321.34</td>\n",
" <td>185.67558</td>\n",
" <td>46321.340000</td>\n",
" <td>46321.340000</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.0</td>\n",
" <td>104.41</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2022-01-01 00:05:00+00:00</th>\n",
" <td>1640995500</td>\n",
" <td>46321.34</td>\n",
" <td>46527.26</td>\n",
" <td>46280.00</td>\n",
" <td>46371.11</td>\n",
" <td>123.43577</td>\n",
" <td>46346.225000</td>\n",
" <td>46346.225000</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.0</td>\n",
" <td>48.45</td>\n",
" <td>0.0</td>\n",
" <td>0.000</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2022-01-01 00:10:00+00:00</th>\n",
" <td>1640995800</td>\n",
" <td>46369.79</td>\n",
" <td>46394.00</td>\n",
" <td>46276.22</td>\n",
" <td>46332.51</td>\n",
" <td>77.54574</td>\n",
" <td>46341.653333</td>\n",
" <td>46341.653333</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.0</td>\n",
" <td>-37.27</td>\n",
" <td>0.0</td>\n",
" <td>-0.000</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2022-01-01 00:15:00+00:00</th>\n",
" <td>1640996100</td>\n",
" <td>46332.52</td>\n",
" <td>46332.52</td>\n",
" <td>46236.27</td>\n",
" <td>46293.90</td>\n",
" <td>101.14315</td>\n",
" <td>46329.715000</td>\n",
" <td>46329.715000</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.0</td>\n",
" <td>-37.10</td>\n",
" <td>0.0</td>\n",
" <td>-0.000</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2022-01-01 00:20:00+00:00</th>\n",
" <td>1640996400</td>\n",
" <td>46295.42</td>\n",
" <td>46421.27</td>\n",
" <td>46286.25</td>\n",
" <td>46395.53</td>\n",
" <td>135.32479</td>\n",
" <td>46342.878000</td>\n",
" <td>46342.878000</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.0</td>\n",
" <td>100.11</td>\n",
" <td>0.0</td>\n",
" <td>0.000</td>\n",
" <td>0.000000</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",
" <td>...</td>\n",
" <td>...</td>\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>2022-12-31 23:35:00+00:00</th>\n",
" <td>1672529700</td>\n",
" <td>16538.17</td>\n",
" <td>16551.24</td>\n",
" <td>16536.84</td>\n",
" <td>16545.68</td>\n",
" <td>501.06148</td>\n",
" <td>16530.430500</td>\n",
" <td>16551.263404</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.5</td>\n",
" <td>7.51</td>\n",
" <td>0.0</td>\n",
" <td>3.755</td>\n",
" <td>7148.928371</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2022-12-31 23:40:00+00:00</th>\n",
" <td>1672530000</td>\n",
" <td>16545.68</td>\n",
" <td>16550.26</td>\n",
" <td>16543.45</td>\n",
" <td>16546.13</td>\n",
" <td>277.70571</td>\n",
" <td>16530.540000</td>\n",
" <td>16550.433191</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.5</td>\n",
" <td>0.46</td>\n",
" <td>0.0</td>\n",
" <td>0.230</td>\n",
" <td>7149.158371</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2022-12-31 23:45:00+00:00</th>\n",
" <td>1672530300</td>\n",
" <td>16546.14</td>\n",
" <td>16550.55</td>\n",
" <td>16536.62</td>\n",
" <td>16539.05</td>\n",
" <td>292.41232</td>\n",
" <td>16529.683500</td>\n",
" <td>16549.552553</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.5</td>\n",
" <td>-7.75</td>\n",
" <td>0.0</td>\n",
" <td>-3.875</td>\n",
" <td>7145.283371</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2022-12-31 23:50:00+00:00</th>\n",
" <td>1672530600</td>\n",
" <td>16538.39</td>\n",
" <td>16541.26</td>\n",
" <td>16534.92</td>\n",
" <td>16540.42</td>\n",
" <td>180.18579</td>\n",
" <td>16528.435500</td>\n",
" <td>16548.920213</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.5</td>\n",
" <td>2.03</td>\n",
" <td>0.0</td>\n",
" <td>1.015</td>\n",
" <td>7146.298371</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2022-12-31 23:55:00+00:00</th>\n",
" <td>1672530900</td>\n",
" <td>16540.42</td>\n",
" <td>16544.47</td>\n",
" <td>16535.05</td>\n",
" <td>16542.40</td>\n",
" <td>227.06684</td>\n",
" <td>16528.974500</td>\n",
" <td>16548.307660</td>\n",
" <td>False</td>\n",
" <td>False</td>\n",
" <td>0</td>\n",
" <td>0.5</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>7146.298371</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>105120 rows × 16 columns</p>\n",
"</div>\n",
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-92a90e67-7959-43b7-8195-b1602f4ab13a')\"\n",
" title=\"Convert this dataframe to an interactive table.\"\n",
" style=\"display:none;\">\n",
" \n",
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
" width=\"24px\">\n",
" <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
" <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
" </svg>\n",
" </button>\n",
" \n",
" <style>\n",
" .colab-df-container {\n",
" display:flex;\n",
" flex-wrap:wrap;\n",
" gap: 12px;\n",
" }\n",
"\n",
" .colab-df-convert {\n",
" background-color: #E8F0FE;\n",
" border: none;\n",
" border-radius: 50%;\n",
" cursor: pointer;\n",
" display: none;\n",
" fill: #1967D2;\n",
" height: 32px;\n",
" padding: 0 0 0 0;\n",
" width: 32px;\n",
" }\n",
"\n",
" .colab-df-convert:hover {\n",
" background-color: #E2EBFA;\n",
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
" fill: #174EA6;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert {\n",
" background-color: #3B4455;\n",
" fill: #D2E3FC;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert:hover {\n",
" background-color: #434B5C;\n",
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
" fill: #FFFFFF;\n",
" }\n",
" </style>\n",
"\n",
" <script>\n",
" const buttonEl =\n",
" document.querySelector('#df-92a90e67-7959-43b7-8195-b1602f4ab13a button.colab-df-convert');\n",
" buttonEl.style.display =\n",
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
"\n",
" async function convertToInteractive(key) {\n",
" const element = document.querySelector('#df-92a90e67-7959-43b7-8195-b1602f4ab13a');\n",
" const dataTable =\n",
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
" [key], {});\n",
" if (!dataTable) return;\n",
"\n",
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
" + ' to learn more about interactive tables.';\n",
" element.innerHTML = '';\n",
" dataTable['output_type'] = 'display_data';\n",
" await google.colab.output.renderOutput(dataTable, element);\n",
" const docLink = document.createElement('div');\n",
" docLink.innerHTML = docLinkHtml;\n",
" element.appendChild(docLink);\n",
" }\n",
" </script>\n",
" </div>\n",
" </div>\n",
" "
]
},
"metadata": {}
}
]
},
{
"cell_type": "markdown",
"source": [
"### polars"
],
"metadata": {
"id": "8adUlBikI7Ia"
}
},
{
"cell_type": "markdown",
"source": [
"#### CSV読み込み"
],
"metadata": {
"id": "kFxI4R6xJ97h"
}
},
{
"cell_type": "code",
"source": [
"s = time.time()\n",
"\n",
"# csvをDataFrameに読み込み\n",
"df_ohlcv_pl = pl.read_csv(CSV_PATH)\n",
"\n",
"ret = round((time.time() - s) * 1000, 3)\n",
"print(f'[処理時間]: {ret} ms\\n')"
],
"metadata": {
"id": "EIhmesRnR5Qj",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "55409498-70c5-4f64-ee49-40ee16215afa"
},
"execution_count": 30,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[処理時間]: 41.912 ms\n",
"\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"#### バックテスト関数\n",
"上記のbacktest_pandas関数をpolarsに置き換えたコードになります。"
],
"metadata": {
"id": "A9YmBDxQKEEm"
}
},
{
"cell_type": "code",
"source": [
"def backtest_polars(short_sma:int, long_sma:int, pyramid:int, df_ohlcv:pl.DataFrame=None) -> pl.DataFrame:\n",
" \"\"\"**【バックテスト(polars)】**\n",
"\n",
" 短期/長期移動平均のゴールデンクロス/デッドクロスでエントリー \n",
" 同方向に注文が重なった場合は指定回数まで積み増し\n",
"\n",
" :param short_sma: 短期 移動平均期間\n",
" :param long_sma: 長期 移動平均期間\n",
" :param pyramid: 積み増し回数\n",
" :param df_ohlcv: OHLCV DataFrame(polars)\n",
"\n",
" :return: 処理結果 DataFrame\n",
" \"\"\"\n",
" global df_ohlcv_pl\n",
"\n",
" if df_ohlcv is None:\n",
" df = df_ohlcv_pl.clone()\n",
" else:\n",
" df = df_ohlcv.clone()\n",
"\n",
" # DataFrame生成\n",
" df = (\n",
" df.lazy()\n",
" .with_columns([ # SMA計算\n",
" # datetime\n",
" (pl.col('timestamp') * NANOSECONDS) # timestamp(秒)をnano秒単位に\n",
" .cast(pl.Datetime(time_unit='ns')) # datetime(nano秒)変換\n",
" .dt.replace_time_zone('UTC') # タイムゾーン設定\n",
" .alias('datetime'),\n",
" # short_sma\n",
" pl.col('close').rolling_mean(short_sma, min_periods=1).alias('short_sma'),\n",
" # long_sma\n",
" pl.col('close').rolling_mean(long_sma, min_periods=1).alias('long_sma'),\n",
" ])\n",
" .with_columns([ # エントリー判定\n",
" # long\n",
" ((pl.col('long_sma').diff(n=1, null_behavior='ignore') > 0) &\n",
" (pl.col('long_sma') - pl.col('short_sma') > 0) &\n",
" (pl.col('long_sma').shift(periods=1) - pl.col('short_sma') < 0)).alias('long'),\n",
" # short\n",
" ((pl.col('long_sma').diff(n=1, null_behavior='ignore') < 0) &\n",
" (pl.col('long_sma') - pl.col('short_sma') < 0) &\n",
" (pl.col('long_sma').shift(periods=1) - pl.col('short_sma') > 0)).alias('short'),\n",
" ])\n",
" .with_columns([ # 注文\n",
" # order\n",
" pl.when(pl.col('long') == True).then(1)\n",
" .when(pl.col('short') == True).then(-1)\n",
" .otherwise(0).alias('order'),\n",
" ])\n",
" .with_columns([ # ポジション計算(ドテン&ピラミッディング)\n",
" # pos\n",
" pl.when(pl.col('order') != 0).then(pl.col('order'))\n",
" .otherwise(None).fill_null(strategy='forward').fill_null(0).alias('pos'),\n",
" ])\n",
" .with_columns([ # ポジション方向がドテンする単位でグループNo.を設定\n",
" # doten_group\n",
" (pl.col('pos') * pl.col('pos').shift(periods=1) < 0).cumsum().fill_null(0).alias('doten_group'),\n",
" ])\n",
" .collect()\n",
" )\n",
"\n",
" # ドテンするグループ内でポジションを積み増し\n",
" df = (\n",
" df.lazy()\n",
" .with_columns(\n",
" # pos\n",
" df.groupby('doten_group')\n",
" .agg(pl.col('order').cumsum())\n",
" .explode('order')\n",
" .sort(by='doten_group')\n",
" .select(pl.col('order').alias('pos'))\n",
" )\n",
" .with_columns([ # ピラミッディング回数でポジションサイズ調整\n",
" # pos\n",
" pl.when(pl.col('pos') > pyramid).then(1)\n",
" .when(pl.col('pos') < -pyramid).then(-1)\n",
" .otherwise(pl.col('pos') / pyramid).alias('pos'),\n",
" ])\n",
" .with_columns([ # 損益計算\n",
" # return\n",
" (pl.col('open').shift(periods=-1) - pl.col('open')).alias('return'),\n",
" # commision\n",
" (pl.col('open').shift(periods=-1) * COMMISION / 100 * abs(pl.col('pos') - pl.col('pos').shift(periods=1))).alias('commision'),\n",
" ])\n",
" .with_columns([\n",
" # profit\n",
" (pl.col('return') * pl.col('pos').shift(periods=1) - pl.col('commision')).alias('profit'),\n",
" ])\n",
" .with_columns([\n",
" # pnl\n",
" (pl.col('profit').cumsum().fill_null(strategy='forward').fill_null(0)).alias('pnl'),\n",
" ])\n",
" .collect()\n",
" )\n",
"\n",
" return df"
],
"metadata": {
"id": "jTYX40cqH-kh"
},
"execution_count": 31,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"#### バックテスト実行"
],
"metadata": {
"id": "ApdiP5uAKMmv"
}
},
{
"cell_type": "code",
"source": [
"s = time.time()\n",
"\n",
"# バックテスト\n",
"df_result_pl = backtest_polars(SHORT_SMA, LONG_SMA, PYRAMIDING, df_ohlcv_pl)\n",
"\n",
"ret = round((time.time() - s) * 1000, 3)\n",
"print(f'[処理時間]: {ret} ms\\n')\n",
"\n",
"# 結果表示\n",
"display(df_result_pl)\n",
"# 結果表示(ポジション変化が有ったところだけ)\n",
"#display(df_result_pl.filter(pl.col('pos').diff(n=1, null_behavior='ignore') != 0).select(pl.col(['open','long','short','pos','pnl'])))"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 1000
},
"id": "Lo0sTQSdblY2",
"outputId": "0f336c5b-87cb-4f23-e61b-691a9fd3bc7b"
},
"execution_count": 42,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[処理時間]: 50.098 ms\n",
"\n"
]
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"shape: (105120, 18)\n",
"┌────────────┬──────────┬──────────┬──────────┬─────┬────────┬───────────┬────────┬─────────────┐\n",
"│ timestamp ┆ open ┆ high ┆ low ┆ ... ┆ return ┆ commision ┆ profit ┆ pnl │\n",
"│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │\n",
"│ i64 ┆ f64 ┆ f64 ┆ f64 ┆ ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n",
"╞════════════╪══════════╪══════════╪══════════╪═════╪════════╪═══════════╪════════╪═════════════╡\n",
"│ 1640995200 ┆ 46216.93 ┆ 46391.49 ┆ 46208.37 ┆ ... ┆ 104.41 ┆ null ┆ null ┆ 0.0 │\n",
"│ 1640995500 ┆ 46321.34 ┆ 46527.26 ┆ 46280.0 ┆ ... ┆ 48.45 ┆ 0.0 ┆ 0.0 ┆ 0.0 │\n",
"│ 1640995800 ┆ 46369.79 ┆ 46394.0 ┆ 46276.22 ┆ ... ┆ -37.27 ┆ 0.0 ┆ -0.0 ┆ 0.0 │\n",
"│ 1640996100 ┆ 46332.52 ┆ 46332.52 ┆ 46236.27 ┆ ... ┆ -37.1 ┆ 0.0 ┆ -0.0 ┆ 0.0 │\n",
"│ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... │\n",
"│ 1672530000 ┆ 16545.68 ┆ 16550.26 ┆ 16543.45 ┆ ... ┆ 0.46 ┆ 0.0 ┆ 0.23 ┆ 7149.158371 │\n",
"│ 1672530300 ┆ 16546.14 ┆ 16550.55 ┆ 16536.62 ┆ ... ┆ -7.75 ┆ 0.0 ┆ -3.875 ┆ 7145.283371 │\n",
"│ 1672530600 ┆ 16538.39 ┆ 16541.26 ┆ 16534.92 ┆ ... ┆ 2.03 ┆ 0.0 ┆ 1.015 ┆ 7146.298371 │\n",
"│ 1672530900 ┆ 16540.42 ┆ 16544.47 ┆ 16535.05 ┆ ... ┆ null ┆ null ┆ null ┆ 7146.298371 │\n",
"└────────────┴──────────┴──────────┴──────────┴─────┴────────┴───────────┴────────┴─────────────┘"
],
"text/html": [
"<div>\n",
"<style>\n",
".pl-dataframe > thead > tr > th {\n",
" text-align: right;\n",
"}\n",
"</style>\n",
"\n",
"<table border=\"1\" class=\"dataframe pl-dataframe\">\n",
"<small>shape: (105120, 18)</small>\n",
"<thead>\n",
"<tr>\n",
"<th>\n",
"timestamp\n",
"</th>\n",
"<th>\n",
"open\n",
"</th>\n",
"<th>\n",
"high\n",
"</th>\n",
"<th>\n",
"low\n",
"</th>\n",
"<th>\n",
"close\n",
"</th>\n",
"<th>\n",
"volume\n",
"</th>\n",
"<th>\n",
"datetime\n",
"</th>\n",
"<th>\n",
"short_sma\n",
"</th>\n",
"<th>\n",
"long_sma\n",
"</th>\n",
"<th>\n",
"long\n",
"</th>\n",
"<th>\n",
"short\n",
"</th>\n",
"<th>\n",
"order\n",
"</th>\n",
"<th>\n",
"pos\n",
"</th>\n",
"<th>\n",
"doten_group\n",
"</th>\n",
"<th>\n",
"return\n",
"</th>\n",
"<th>\n",
"commision\n",
"</th>\n",
"<th>\n",
"profit\n",
"</th>\n",
"<th>\n",
"pnl\n",
"</th>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"i64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"datetime[ns, UTC]\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"bool\n",
"</td>\n",
"<td>\n",
"bool\n",
"</td>\n",
"<td>\n",
"i32\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"u32\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"</tr>\n",
"</thead>\n",
"<tbody>\n",
"<tr>\n",
"<td>\n",
"1640995200\n",
"</td>\n",
"<td>\n",
"46216.93\n",
"</td>\n",
"<td>\n",
"46391.49\n",
"</td>\n",
"<td>\n",
"46208.37\n",
"</td>\n",
"<td>\n",
"46321.34\n",
"</td>\n",
"<td>\n",
"185.67558\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:00:00 UTC\n",
"</td>\n",
"<td>\n",
"46321.34\n",
"</td>\n",
"<td>\n",
"46321.34\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"104.41\n",
"</td>\n",
"<td>\n",
"null\n",
"</td>\n",
"<td>\n",
"null\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640995500\n",
"</td>\n",
"<td>\n",
"46321.34\n",
"</td>\n",
"<td>\n",
"46527.26\n",
"</td>\n",
"<td>\n",
"46280.0\n",
"</td>\n",
"<td>\n",
"46371.11\n",
"</td>\n",
"<td>\n",
"123.43577\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:05:00 UTC\n",
"</td>\n",
"<td>\n",
"46346.225\n",
"</td>\n",
"<td>\n",
"46346.225\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"48.45\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640995800\n",
"</td>\n",
"<td>\n",
"46369.79\n",
"</td>\n",
"<td>\n",
"46394.0\n",
"</td>\n",
"<td>\n",
"46276.22\n",
"</td>\n",
"<td>\n",
"46332.51\n",
"</td>\n",
"<td>\n",
"77.54574\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:10:00 UTC\n",
"</td>\n",
"<td>\n",
"46341.653333\n",
"</td>\n",
"<td>\n",
"46341.653333\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"-37.27\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640996100\n",
"</td>\n",
"<td>\n",
"46332.52\n",
"</td>\n",
"<td>\n",
"46332.52\n",
"</td>\n",
"<td>\n",
"46236.27\n",
"</td>\n",
"<td>\n",
"46293.9\n",
"</td>\n",
"<td>\n",
"101.14315\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:15:00 UTC\n",
"</td>\n",
"<td>\n",
"46329.715\n",
"</td>\n",
"<td>\n",
"46329.715\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"-37.1\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640996400\n",
"</td>\n",
"<td>\n",
"46295.42\n",
"</td>\n",
"<td>\n",
"46421.27\n",
"</td>\n",
"<td>\n",
"46286.25\n",
"</td>\n",
"<td>\n",
"46395.53\n",
"</td>\n",
"<td>\n",
"135.32479\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:20:00 UTC\n",
"</td>\n",
"<td>\n",
"46342.878\n",
"</td>\n",
"<td>\n",
"46342.878\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"100.11\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640996700\n",
"</td>\n",
"<td>\n",
"46395.53\n",
"</td>\n",
"<td>\n",
"46400.38\n",
"</td>\n",
"<td>\n",
"46345.1\n",
"</td>\n",
"<td>\n",
"46375.42\n",
"</td>\n",
"<td>\n",
"83.53179\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:25:00 UTC\n",
"</td>\n",
"<td>\n",
"46348.301667\n",
"</td>\n",
"<td>\n",
"46348.301667\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"-20.11\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640997000\n",
"</td>\n",
"<td>\n",
"46375.42\n",
"</td>\n",
"<td>\n",
"46446.47\n",
"</td>\n",
"<td>\n",
"46360.19\n",
"</td>\n",
"<td>\n",
"46443.65\n",
"</td>\n",
"<td>\n",
"81.82606\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:30:00 UTC\n",
"</td>\n",
"<td>\n",
"46361.922857\n",
"</td>\n",
"<td>\n",
"46361.922857\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"68.23\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640997300\n",
"</td>\n",
"<td>\n",
"46443.65\n",
"</td>\n",
"<td>\n",
"46590.0\n",
"</td>\n",
"<td>\n",
"46443.64\n",
"</td>\n",
"<td>\n",
"46530.7\n",
"</td>\n",
"<td>\n",
"113.11574\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:35:00 UTC\n",
"</td>\n",
"<td>\n",
"46383.02\n",
"</td>\n",
"<td>\n",
"46383.02\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"87.06\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640997600\n",
"</td>\n",
"<td>\n",
"46530.71\n",
"</td>\n",
"<td>\n",
"46689.42\n",
"</td>\n",
"<td>\n",
"46503.51\n",
"</td>\n",
"<td>\n",
"46610.81\n",
"</td>\n",
"<td>\n",
"191.13897\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:40:00 UTC\n",
"</td>\n",
"<td>\n",
"46408.33\n",
"</td>\n",
"<td>\n",
"46408.33\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"80.1\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640997900\n",
"</td>\n",
"<td>\n",
"46610.81\n",
"</td>\n",
"<td>\n",
"46731.39\n",
"</td>\n",
"<td>\n",
"46575.76\n",
"</td>\n",
"<td>\n",
"46693.74\n",
"</td>\n",
"<td>\n",
"168.66367\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:45:00 UTC\n",
"</td>\n",
"<td>\n",
"46436.871\n",
"</td>\n",
"<td>\n",
"46436.871\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"82.94\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640998200\n",
"</td>\n",
"<td>\n",
"46693.75\n",
"</td>\n",
"<td>\n",
"46708.59\n",
"</td>\n",
"<td>\n",
"46628.6\n",
"</td>\n",
"<td>\n",
"46659.65\n",
"</td>\n",
"<td>\n",
"133.40734\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:50:00 UTC\n",
"</td>\n",
"<td>\n",
"46457.123636\n",
"</td>\n",
"<td>\n",
"46457.123636\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"-34.09\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1640998500\n",
"</td>\n",
"<td>\n",
"46659.66\n",
"</td>\n",
"<td>\n",
"46690.16\n",
"</td>\n",
"<td>\n",
"46630.46\n",
"</td>\n",
"<td>\n",
"46656.13\n",
"</td>\n",
"<td>\n",
"108.52235\n",
"</td>\n",
"<td>\n",
"2022-01-01 00:55:00 UTC\n",
"</td>\n",
"<td>\n",
"46473.7075\n",
"</td>\n",
"<td>\n",
"46473.7075\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"-3.52\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672527600\n",
"</td>\n",
"<td>\n",
"16520.28\n",
"</td>\n",
"<td>\n",
"16524.91\n",
"</td>\n",
"<td>\n",
"16500.24\n",
"</td>\n",
"<td>\n",
"16506.14\n",
"</td>\n",
"<td>\n",
"767.72112\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:00:00 UTC\n",
"</td>\n",
"<td>\n",
"16542.4405\n",
"</td>\n",
"<td>\n",
"16559.298085\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"-14.14\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-7.07\n",
"</td>\n",
"<td>\n",
"7129.158371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672527900\n",
"</td>\n",
"<td>\n",
"16506.14\n",
"</td>\n",
"<td>\n",
"16514.99\n",
"</td>\n",
"<td>\n",
"16490.78\n",
"</td>\n",
"<td>\n",
"16495.24\n",
"</td>\n",
"<td>\n",
"558.92871\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:05:00 UTC\n",
"</td>\n",
"<td>\n",
"16539.0105\n",
"</td>\n",
"<td>\n",
"16557.58\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"-10.13\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-5.065\n",
"</td>\n",
"<td>\n",
"7124.093371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672528200\n",
"</td>\n",
"<td>\n",
"16496.01\n",
"</td>\n",
"<td>\n",
"16503.97\n",
"</td>\n",
"<td>\n",
"16487.74\n",
"</td>\n",
"<td>\n",
"16502.67\n",
"</td>\n",
"<td>\n",
"555.3314\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:10:00 UTC\n",
"</td>\n",
"<td>\n",
"16536.248\n",
"</td>\n",
"<td>\n",
"16556.038936\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"6.66\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"3.33\n",
"</td>\n",
"<td>\n",
"7127.423371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672528500\n",
"</td>\n",
"<td>\n",
"16502.67\n",
"</td>\n",
"<td>\n",
"16526.51\n",
"</td>\n",
"<td>\n",
"16500.73\n",
"</td>\n",
"<td>\n",
"16523.86\n",
"</td>\n",
"<td>\n",
"618.0961\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:15:00 UTC\n",
"</td>\n",
"<td>\n",
"16534.4375\n",
"</td>\n",
"<td>\n",
"16555.104681\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"21.19\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"10.595\n",
"</td>\n",
"<td>\n",
"7138.018371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672528800\n",
"</td>\n",
"<td>\n",
"16523.86\n",
"</td>\n",
"<td>\n",
"16529.54\n",
"</td>\n",
"<td>\n",
"16520.91\n",
"</td>\n",
"<td>\n",
"16525.92\n",
"</td>\n",
"<td>\n",
"302.37991\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:20:00 UTC\n",
"</td>\n",
"<td>\n",
"16532.707\n",
"</td>\n",
"<td>\n",
"16554.120638\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"2.68\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"1.34\n",
"</td>\n",
"<td>\n",
"7139.358371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672529100\n",
"</td>\n",
"<td>\n",
"16526.54\n",
"</td>\n",
"<td>\n",
"16527.01\n",
"</td>\n",
"<td>\n",
"16517.51\n",
"</td>\n",
"<td>\n",
"16524.64\n",
"</td>\n",
"<td>\n",
"262.99128\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:25:00 UTC\n",
"</td>\n",
"<td>\n",
"16531.1315\n",
"</td>\n",
"<td>\n",
"16552.990213\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"-1.89\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.945\n",
"</td>\n",
"<td>\n",
"7138.413371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672529400\n",
"</td>\n",
"<td>\n",
"16524.65\n",
"</td>\n",
"<td>\n",
"16540.59\n",
"</td>\n",
"<td>\n",
"16520.44\n",
"</td>\n",
"<td>\n",
"16538.17\n",
"</td>\n",
"<td>\n",
"429.55241\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:30:00 UTC\n",
"</td>\n",
"<td>\n",
"16530.5605\n",
"</td>\n",
"<td>\n",
"16551.932766\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"13.52\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"6.76\n",
"</td>\n",
"<td>\n",
"7145.173371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672529700\n",
"</td>\n",
"<td>\n",
"16538.17\n",
"</td>\n",
"<td>\n",
"16551.24\n",
"</td>\n",
"<td>\n",
"16536.84\n",
"</td>\n",
"<td>\n",
"16545.68\n",
"</td>\n",
"<td>\n",
"501.06148\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:35:00 UTC\n",
"</td>\n",
"<td>\n",
"16530.4305\n",
"</td>\n",
"<td>\n",
"16551.263404\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"7.51\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"3.755\n",
"</td>\n",
"<td>\n",
"7148.928371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672530000\n",
"</td>\n",
"<td>\n",
"16545.68\n",
"</td>\n",
"<td>\n",
"16550.26\n",
"</td>\n",
"<td>\n",
"16543.45\n",
"</td>\n",
"<td>\n",
"16546.13\n",
"</td>\n",
"<td>\n",
"277.70571\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:40:00 UTC\n",
"</td>\n",
"<td>\n",
"16530.54\n",
"</td>\n",
"<td>\n",
"16550.433191\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"0.46\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.23\n",
"</td>\n",
"<td>\n",
"7149.158371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672530300\n",
"</td>\n",
"<td>\n",
"16546.14\n",
"</td>\n",
"<td>\n",
"16550.55\n",
"</td>\n",
"<td>\n",
"16536.62\n",
"</td>\n",
"<td>\n",
"16539.05\n",
"</td>\n",
"<td>\n",
"292.41232\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:45:00 UTC\n",
"</td>\n",
"<td>\n",
"16529.6835\n",
"</td>\n",
"<td>\n",
"16549.552553\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"-7.75\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-3.875\n",
"</td>\n",
"<td>\n",
"7145.283371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672530600\n",
"</td>\n",
"<td>\n",
"16538.39\n",
"</td>\n",
"<td>\n",
"16541.26\n",
"</td>\n",
"<td>\n",
"16534.92\n",
"</td>\n",
"<td>\n",
"16540.42\n",
"</td>\n",
"<td>\n",
"180.18579\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:50:00 UTC\n",
"</td>\n",
"<td>\n",
"16528.4355\n",
"</td>\n",
"<td>\n",
"16548.920213\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"2.03\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"1.015\n",
"</td>\n",
"<td>\n",
"7146.298371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"1672530900\n",
"</td>\n",
"<td>\n",
"16540.42\n",
"</td>\n",
"<td>\n",
"16544.47\n",
"</td>\n",
"<td>\n",
"16535.05\n",
"</td>\n",
"<td>\n",
"16542.4\n",
"</td>\n",
"<td>\n",
"227.06684\n",
"</td>\n",
"<td>\n",
"2022-12-31 23:55:00 UTC\n",
"</td>\n",
"<td>\n",
"16528.9745\n",
"</td>\n",
"<td>\n",
"16548.30766\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"false\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"440\n",
"</td>\n",
"<td>\n",
"null\n",
"</td>\n",
"<td>\n",
"null\n",
"</td>\n",
"<td>\n",
"null\n",
"</td>\n",
"<td>\n",
"7146.298371\n",
"</td>\n",
"</tr>\n",
"</tbody>\n",
"</table>\n",
"</div>"
]
},
"metadata": {}
}
]
},
{
"cell_type": "markdown",
"source": [
"#### (調整版)バックテスト関数\n",
"上記のbacktest_polars関数をベースにピラミッディングのポジション計算にgroupbyを使用せず、損益計算までワンライナーで処理するように調整したコードになります。"
],
"metadata": {
"id": "_hrrqn9YKi2S"
}
},
{
"cell_type": "code",
"source": [
"def backtest_polars2(short_sma:int, long_sma:int, pyramid:int, df_ohlcv:pl.DataFrame=None) -> pl.DataFrame:\n",
" \"\"\"**【バックテスト(polars)】**\n",
"\n",
" 短期/長期移動平均のゴールデンクロス/デッドクロスでエントリー \n",
" 同方向に注文が重なった場合は指定回数まで積み増し\n",
"\n",
" :param short_sma: 短期 移動平均期間\n",
" :param long_sma: 長期 移動平均期間\n",
" :param pyramid: 積み増し回数\n",
" :param df_ohlcv: OHLCV DataFrame(polars)\n",
"\n",
" :return: 処理結果 DataFrame\n",
" \"\"\"\n",
" global df_ohlcv_pl\n",
"\n",
" if df_ohlcv is None:\n",
" df = df_ohlcv_pl.clone()\n",
" else:\n",
" df = df_ohlcv.clone()\n",
"\n",
" # DataFrame生成\n",
" df = (\n",
" df.lazy()\n",
" .with_columns([ # SMA計算\n",
" # datetime\n",
" (pl.col('timestamp') * NANOSECONDS) # timestamp(秒)をnano秒単位に\n",
" .cast(pl.Datetime(time_unit='ns')) # datetime(nano秒)変換\n",
" .dt.replace_time_zone('UTC') # タイムゾーン設定\n",
" .alias('datetime'),\n",
" # short_sma\n",
" pl.col('close').rolling_mean(short_sma, min_periods=1).alias('short_sma'),\n",
" # long_sma\n",
" pl.col('close').rolling_mean(long_sma, min_periods=1).alias('long_sma'),\n",
" ])\n",
" .with_columns([ # エントリー判定\n",
" # long(1)\n",
" pl.when((pl.col('long_sma').diff(n=1, null_behavior='ignore') > 0) &\n",
" (pl.col('long_sma') - pl.col('short_sma') > 0) &\n",
" (pl.col('long_sma').shift(periods=1) - pl.col('short_sma') < 0)).then(1)\n",
" # short(-1)\n",
" .when((pl.col('long_sma').diff(n=1, null_behavior='ignore') < 0) &\n",
" (pl.col('long_sma') - pl.col('short_sma') < 0) &\n",
" (pl.col('long_sma').shift(periods=1) - pl.col('short_sma') > 0)).then(-1)\n",
" # none(0)\n",
" .otherwise(0).alias('order'),\n",
" ])\n",
" .with_columns([ # ポジション方向(ドテン判定のため)\n",
" # side\n",
" pl.when(pl.col('order') != 0).then(pl.col('order'))\n",
" .otherwise(None).fill_null(strategy='forward').fill_null(0).alias('side'),\n",
" ])\n",
" .with_columns([ # ポジション方向がドテンする単位でグループNo.を設定\n",
" # doten_group\n",
" (pl.col('side') * pl.col('side').shift(periods=1) < 0).cumsum().fill_null(0).alias('doten_group'),\n",
" # order_cumsum\n",
" pl.col('order').cumsum().alias('order_cumsum'), # ポジションサイズ計算のため、order累積和\n",
" ])\n",
" .with_columns([ # ドテン時にorder累積和をリセットする調整サイズ\n",
" # doten_reset\n",
" pl.when(pl.col('doten_group').diff(n=1, null_behavior='ignore') != 0).then(pl.col('order_cumsum').shift(periods=1) * -1)\n",
" .otherwise(None).fill_null(strategy='forward').fill_null(0).alias('doten_reset'),\n",
" ])\n",
" .with_columns([ # ポジション計算(order累積和&調整サイズ)\n",
" # pos\n",
" (pl.col('order_cumsum') + pl.col('doten_reset')).alias('pos'),\n",
" ])\n",
" .with_columns([ # ピラミッディング回数でポジションサイズ調整\n",
" # pos\n",
" pl.when(pl.col('pos') > pyramid).then(1)\n",
" .when(pl.col('pos') < -pyramid).then(-1)\n",
" .otherwise(pl.col('pos') / pyramid).alias('pos'),\n",
" ])\n",
" .with_columns([ # 損益計算\n",
" # return\n",
" (pl.col('open').shift(periods=-1) - pl.col('open')).alias('return'),\n",
" # commision\n",
" (pl.col('open').shift(periods=-1) * COMMISION / 100 * abs(pl.col('pos') - pl.col('pos').shift(periods=1))).fill_null(0).alias('commision'),\n",
" ])\n",
" .with_columns([\n",
" # profit\n",
" (pl.col('return') * pl.col('pos').shift(periods=1) - pl.col('commision')).alias('profit'),\n",
" ])\n",
" .with_columns([\n",
" # pnl\n",
" (pl.col('profit').cumsum().fill_null(strategy='forward').fill_null(0)).alias('pnl'),\n",
" ])\n",
" .collect()\n",
" )\n",
"\n",
" return df"
],
"metadata": {
"id": "JJRzi7YGPM8a"
},
"execution_count": 33,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"#### (調整版)バックテスト実行"
],
"metadata": {
"id": "jmbjOdA4LxNE"
}
},
{
"cell_type": "code",
"source": [
"s = time.time()\n",
"\n",
"# バックテスト\n",
"df_result_pl2 = backtest_polars2(SHORT_SMA, LONG_SMA, PYRAMIDING, df_ohlcv_pl)\n",
"\n",
"ret = round((time.time() - s) * 1000, 3)\n",
"print(f'[処理時間]: {ret} ms\\n')\n",
"\n",
"# 結果表示\n",
"display(df_result_pl2.select(pl.col(['datetime','open','high','low','close','volume','short_sma','long_sma','order','pos','return','commision','profit','pnl'])))\n",
"# 結果表示(ポジション変化が有ったところだけ)\n",
"#display(df_result_pl2.filter(pl.col('pos').diff(n=1, null_behavior='ignore') != 0).select(pl.col(['open','long','short','pos','pnl'])))"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 917
},
"id": "Dd4LMw3sUbrL",
"outputId": "4a0826ff-5268-4a26-cf29-b7854195b82a"
},
"execution_count": 39,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[処理時間]: 38.621 ms\n",
"\n"
]
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"shape: (105120, 14)\n",
"┌───────────────┬──────────┬──────────┬──────────┬─────┬────────┬───────────┬────────┬─────────────┐\n",
"│ datetime ┆ open ┆ high ┆ low ┆ ... ┆ return ┆ commision ┆ profit ┆ pnl │\n",
"│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │\n",
"│ datetime[ns, ┆ f64 ┆ f64 ┆ f64 ┆ ┆ f64 ┆ f64 ┆ f64 ┆ f64 │\n",
"│ UTC] ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"╞═══════════════╪══════════╪══════════╪══════════╪═════╪════════╪═══════════╪════════╪═════════════╡\n",
"│ 2022-01-01 ┆ 46216.93 ┆ 46391.49 ┆ 46208.37 ┆ ... ┆ 104.41 ┆ 0.0 ┆ null ┆ 0.0 │\n",
"│ 00:00:00 UTC ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ 2022-01-01 ┆ 46321.34 ┆ 46527.26 ┆ 46280.0 ┆ ... ┆ 48.45 ┆ 0.0 ┆ 0.0 ┆ 0.0 │\n",
"│ 00:05:00 UTC ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ 2022-01-01 ┆ 46369.79 ┆ 46394.0 ┆ 46276.22 ┆ ... ┆ -37.27 ┆ 0.0 ┆ -0.0 ┆ 0.0 │\n",
"│ 00:10:00 UTC ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ 2022-01-01 ┆ 46332.52 ┆ 46332.52 ┆ 46236.27 ┆ ... ┆ -37.1 ┆ 0.0 ┆ -0.0 ┆ 0.0 │\n",
"│ 00:15:00 UTC ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... │\n",
"│ 2022-12-31 ┆ 16545.68 ┆ 16550.26 ┆ 16543.45 ┆ ... ┆ 0.46 ┆ 0.0 ┆ 0.23 ┆ 7149.158371 │\n",
"│ 23:40:00 UTC ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ 2022-12-31 ┆ 16546.14 ┆ 16550.55 ┆ 16536.62 ┆ ... ┆ -7.75 ┆ 0.0 ┆ -3.875 ┆ 7145.283371 │\n",
"│ 23:45:00 UTC ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ 2022-12-31 ┆ 16538.39 ┆ 16541.26 ┆ 16534.92 ┆ ... ┆ 2.03 ┆ 0.0 ┆ 1.015 ┆ 7146.298371 │\n",
"│ 23:50:00 UTC ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ 2022-12-31 ┆ 16540.42 ┆ 16544.47 ┆ 16535.05 ┆ ... ┆ null ┆ 0.0 ┆ null ┆ 7146.298371 │\n",
"│ 23:55:00 UTC ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"└───────────────┴──────────┴──────────┴──────────┴─────┴────────┴───────────┴────────┴─────────────┘"
],
"text/html": [
"<div>\n",
"<style>\n",
".pl-dataframe > thead > tr > th {\n",
" text-align: right;\n",
"}\n",
"</style>\n",
"\n",
"<table border=\"1\" class=\"dataframe pl-dataframe\">\n",
"<small>shape: (105120, 14)</small>\n",
"<thead>\n",
"<tr>\n",
"<th>\n",
"datetime\n",
"</th>\n",
"<th>\n",
"open\n",
"</th>\n",
"<th>\n",
"high\n",
"</th>\n",
"<th>\n",
"low\n",
"</th>\n",
"<th>\n",
"close\n",
"</th>\n",
"<th>\n",
"volume\n",
"</th>\n",
"<th>\n",
"short_sma\n",
"</th>\n",
"<th>\n",
"long_sma\n",
"</th>\n",
"<th>\n",
"order\n",
"</th>\n",
"<th>\n",
"pos\n",
"</th>\n",
"<th>\n",
"return\n",
"</th>\n",
"<th>\n",
"commision\n",
"</th>\n",
"<th>\n",
"profit\n",
"</th>\n",
"<th>\n",
"pnl\n",
"</th>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"datetime[ns, UTC]\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"i32\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"</tr>\n",
"</thead>\n",
"<tbody>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:00:00 UTC\n",
"</td>\n",
"<td>\n",
"46216.93\n",
"</td>\n",
"<td>\n",
"46391.49\n",
"</td>\n",
"<td>\n",
"46208.37\n",
"</td>\n",
"<td>\n",
"46321.34\n",
"</td>\n",
"<td>\n",
"185.67558\n",
"</td>\n",
"<td>\n",
"46321.34\n",
"</td>\n",
"<td>\n",
"46321.34\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"104.41\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"null\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:05:00 UTC\n",
"</td>\n",
"<td>\n",
"46321.34\n",
"</td>\n",
"<td>\n",
"46527.26\n",
"</td>\n",
"<td>\n",
"46280.0\n",
"</td>\n",
"<td>\n",
"46371.11\n",
"</td>\n",
"<td>\n",
"123.43577\n",
"</td>\n",
"<td>\n",
"46346.225\n",
"</td>\n",
"<td>\n",
"46346.225\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"48.45\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:10:00 UTC\n",
"</td>\n",
"<td>\n",
"46369.79\n",
"</td>\n",
"<td>\n",
"46394.0\n",
"</td>\n",
"<td>\n",
"46276.22\n",
"</td>\n",
"<td>\n",
"46332.51\n",
"</td>\n",
"<td>\n",
"77.54574\n",
"</td>\n",
"<td>\n",
"46341.653333\n",
"</td>\n",
"<td>\n",
"46341.653333\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-37.27\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:15:00 UTC\n",
"</td>\n",
"<td>\n",
"46332.52\n",
"</td>\n",
"<td>\n",
"46332.52\n",
"</td>\n",
"<td>\n",
"46236.27\n",
"</td>\n",
"<td>\n",
"46293.9\n",
"</td>\n",
"<td>\n",
"101.14315\n",
"</td>\n",
"<td>\n",
"46329.715\n",
"</td>\n",
"<td>\n",
"46329.715\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-37.1\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:20:00 UTC\n",
"</td>\n",
"<td>\n",
"46295.42\n",
"</td>\n",
"<td>\n",
"46421.27\n",
"</td>\n",
"<td>\n",
"46286.25\n",
"</td>\n",
"<td>\n",
"46395.53\n",
"</td>\n",
"<td>\n",
"135.32479\n",
"</td>\n",
"<td>\n",
"46342.878\n",
"</td>\n",
"<td>\n",
"46342.878\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"100.11\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:25:00 UTC\n",
"</td>\n",
"<td>\n",
"46395.53\n",
"</td>\n",
"<td>\n",
"46400.38\n",
"</td>\n",
"<td>\n",
"46345.1\n",
"</td>\n",
"<td>\n",
"46375.42\n",
"</td>\n",
"<td>\n",
"83.53179\n",
"</td>\n",
"<td>\n",
"46348.301667\n",
"</td>\n",
"<td>\n",
"46348.301667\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-20.11\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:30:00 UTC\n",
"</td>\n",
"<td>\n",
"46375.42\n",
"</td>\n",
"<td>\n",
"46446.47\n",
"</td>\n",
"<td>\n",
"46360.19\n",
"</td>\n",
"<td>\n",
"46443.65\n",
"</td>\n",
"<td>\n",
"81.82606\n",
"</td>\n",
"<td>\n",
"46361.922857\n",
"</td>\n",
"<td>\n",
"46361.922857\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"68.23\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:35:00 UTC\n",
"</td>\n",
"<td>\n",
"46443.65\n",
"</td>\n",
"<td>\n",
"46590.0\n",
"</td>\n",
"<td>\n",
"46443.64\n",
"</td>\n",
"<td>\n",
"46530.7\n",
"</td>\n",
"<td>\n",
"113.11574\n",
"</td>\n",
"<td>\n",
"46383.02\n",
"</td>\n",
"<td>\n",
"46383.02\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"87.06\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:40:00 UTC\n",
"</td>\n",
"<td>\n",
"46530.71\n",
"</td>\n",
"<td>\n",
"46689.42\n",
"</td>\n",
"<td>\n",
"46503.51\n",
"</td>\n",
"<td>\n",
"46610.81\n",
"</td>\n",
"<td>\n",
"191.13897\n",
"</td>\n",
"<td>\n",
"46408.33\n",
"</td>\n",
"<td>\n",
"46408.33\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"80.1\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:45:00 UTC\n",
"</td>\n",
"<td>\n",
"46610.81\n",
"</td>\n",
"<td>\n",
"46731.39\n",
"</td>\n",
"<td>\n",
"46575.76\n",
"</td>\n",
"<td>\n",
"46693.74\n",
"</td>\n",
"<td>\n",
"168.66367\n",
"</td>\n",
"<td>\n",
"46436.871\n",
"</td>\n",
"<td>\n",
"46436.871\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"82.94\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:50:00 UTC\n",
"</td>\n",
"<td>\n",
"46693.75\n",
"</td>\n",
"<td>\n",
"46708.59\n",
"</td>\n",
"<td>\n",
"46628.6\n",
"</td>\n",
"<td>\n",
"46659.65\n",
"</td>\n",
"<td>\n",
"133.40734\n",
"</td>\n",
"<td>\n",
"46457.123636\n",
"</td>\n",
"<td>\n",
"46457.123636\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-34.09\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-01-01 00:55:00 UTC\n",
"</td>\n",
"<td>\n",
"46659.66\n",
"</td>\n",
"<td>\n",
"46690.16\n",
"</td>\n",
"<td>\n",
"46630.46\n",
"</td>\n",
"<td>\n",
"46656.13\n",
"</td>\n",
"<td>\n",
"108.52235\n",
"</td>\n",
"<td>\n",
"46473.7075\n",
"</td>\n",
"<td>\n",
"46473.7075\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-3.52\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.0\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:00:00 UTC\n",
"</td>\n",
"<td>\n",
"16520.28\n",
"</td>\n",
"<td>\n",
"16524.91\n",
"</td>\n",
"<td>\n",
"16500.24\n",
"</td>\n",
"<td>\n",
"16506.14\n",
"</td>\n",
"<td>\n",
"767.72112\n",
"</td>\n",
"<td>\n",
"16542.4405\n",
"</td>\n",
"<td>\n",
"16559.298085\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"-14.14\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-7.07\n",
"</td>\n",
"<td>\n",
"7129.158371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:05:00 UTC\n",
"</td>\n",
"<td>\n",
"16506.14\n",
"</td>\n",
"<td>\n",
"16514.99\n",
"</td>\n",
"<td>\n",
"16490.78\n",
"</td>\n",
"<td>\n",
"16495.24\n",
"</td>\n",
"<td>\n",
"558.92871\n",
"</td>\n",
"<td>\n",
"16539.0105\n",
"</td>\n",
"<td>\n",
"16557.58\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"-10.13\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-5.065\n",
"</td>\n",
"<td>\n",
"7124.093371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:10:00 UTC\n",
"</td>\n",
"<td>\n",
"16496.01\n",
"</td>\n",
"<td>\n",
"16503.97\n",
"</td>\n",
"<td>\n",
"16487.74\n",
"</td>\n",
"<td>\n",
"16502.67\n",
"</td>\n",
"<td>\n",
"555.3314\n",
"</td>\n",
"<td>\n",
"16536.248\n",
"</td>\n",
"<td>\n",
"16556.038936\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"6.66\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"3.33\n",
"</td>\n",
"<td>\n",
"7127.423371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:15:00 UTC\n",
"</td>\n",
"<td>\n",
"16502.67\n",
"</td>\n",
"<td>\n",
"16526.51\n",
"</td>\n",
"<td>\n",
"16500.73\n",
"</td>\n",
"<td>\n",
"16523.86\n",
"</td>\n",
"<td>\n",
"618.0961\n",
"</td>\n",
"<td>\n",
"16534.4375\n",
"</td>\n",
"<td>\n",
"16555.104681\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"21.19\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"10.595\n",
"</td>\n",
"<td>\n",
"7138.018371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:20:00 UTC\n",
"</td>\n",
"<td>\n",
"16523.86\n",
"</td>\n",
"<td>\n",
"16529.54\n",
"</td>\n",
"<td>\n",
"16520.91\n",
"</td>\n",
"<td>\n",
"16525.92\n",
"</td>\n",
"<td>\n",
"302.37991\n",
"</td>\n",
"<td>\n",
"16532.707\n",
"</td>\n",
"<td>\n",
"16554.120638\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"2.68\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"1.34\n",
"</td>\n",
"<td>\n",
"7139.358371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:25:00 UTC\n",
"</td>\n",
"<td>\n",
"16526.54\n",
"</td>\n",
"<td>\n",
"16527.01\n",
"</td>\n",
"<td>\n",
"16517.51\n",
"</td>\n",
"<td>\n",
"16524.64\n",
"</td>\n",
"<td>\n",
"262.99128\n",
"</td>\n",
"<td>\n",
"16531.1315\n",
"</td>\n",
"<td>\n",
"16552.990213\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"-1.89\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-0.945\n",
"</td>\n",
"<td>\n",
"7138.413371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:30:00 UTC\n",
"</td>\n",
"<td>\n",
"16524.65\n",
"</td>\n",
"<td>\n",
"16540.59\n",
"</td>\n",
"<td>\n",
"16520.44\n",
"</td>\n",
"<td>\n",
"16538.17\n",
"</td>\n",
"<td>\n",
"429.55241\n",
"</td>\n",
"<td>\n",
"16530.5605\n",
"</td>\n",
"<td>\n",
"16551.932766\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"13.52\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"6.76\n",
"</td>\n",
"<td>\n",
"7145.173371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:35:00 UTC\n",
"</td>\n",
"<td>\n",
"16538.17\n",
"</td>\n",
"<td>\n",
"16551.24\n",
"</td>\n",
"<td>\n",
"16536.84\n",
"</td>\n",
"<td>\n",
"16545.68\n",
"</td>\n",
"<td>\n",
"501.06148\n",
"</td>\n",
"<td>\n",
"16530.4305\n",
"</td>\n",
"<td>\n",
"16551.263404\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"7.51\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"3.755\n",
"</td>\n",
"<td>\n",
"7148.928371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:40:00 UTC\n",
"</td>\n",
"<td>\n",
"16545.68\n",
"</td>\n",
"<td>\n",
"16550.26\n",
"</td>\n",
"<td>\n",
"16543.45\n",
"</td>\n",
"<td>\n",
"16546.13\n",
"</td>\n",
"<td>\n",
"277.70571\n",
"</td>\n",
"<td>\n",
"16530.54\n",
"</td>\n",
"<td>\n",
"16550.433191\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"0.46\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"0.23\n",
"</td>\n",
"<td>\n",
"7149.158371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:45:00 UTC\n",
"</td>\n",
"<td>\n",
"16546.14\n",
"</td>\n",
"<td>\n",
"16550.55\n",
"</td>\n",
"<td>\n",
"16536.62\n",
"</td>\n",
"<td>\n",
"16539.05\n",
"</td>\n",
"<td>\n",
"292.41232\n",
"</td>\n",
"<td>\n",
"16529.6835\n",
"</td>\n",
"<td>\n",
"16549.552553\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"-7.75\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"-3.875\n",
"</td>\n",
"<td>\n",
"7145.283371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:50:00 UTC\n",
"</td>\n",
"<td>\n",
"16538.39\n",
"</td>\n",
"<td>\n",
"16541.26\n",
"</td>\n",
"<td>\n",
"16534.92\n",
"</td>\n",
"<td>\n",
"16540.42\n",
"</td>\n",
"<td>\n",
"180.18579\n",
"</td>\n",
"<td>\n",
"16528.4355\n",
"</td>\n",
"<td>\n",
"16548.920213\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"2.03\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"1.015\n",
"</td>\n",
"<td>\n",
"7146.298371\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"2022-12-31 23:55:00 UTC\n",
"</td>\n",
"<td>\n",
"16540.42\n",
"</td>\n",
"<td>\n",
"16544.47\n",
"</td>\n",
"<td>\n",
"16535.05\n",
"</td>\n",
"<td>\n",
"16542.4\n",
"</td>\n",
"<td>\n",
"227.06684\n",
"</td>\n",
"<td>\n",
"16528.9745\n",
"</td>\n",
"<td>\n",
"16548.30766\n",
"</td>\n",
"<td>\n",
"0\n",
"</td>\n",
"<td>\n",
"0.5\n",
"</td>\n",
"<td>\n",
"null\n",
"</td>\n",
"<td>\n",
"0.0\n",
"</td>\n",
"<td>\n",
"null\n",
"</td>\n",
"<td>\n",
"7146.298371\n",
"</td>\n",
"</tr>\n",
"</tbody>\n",
"</table>\n",
"</div>"
]
},
"metadata": {}
}
]
},
{
"cell_type": "markdown",
"source": [
"## 【一括バックテスト】"
],
"metadata": {
"id": "MkVGGcb3LP5b"
}
},
{
"cell_type": "markdown",
"source": [
"### パラメータ組み合わせ設定\n",
"短期/長期移動平均とピラミッディング回数を定義してパラメータの全組み合わせを作成"
],
"metadata": {
"id": "a91uES3OLZYE"
}
},
{
"cell_type": "code",
"source": [
"import itertools\n",
"\n",
"#-----------------------------------------------------------\n",
"# [パラメータリスト]\n",
"SMA_LIST = [3,5,6,10,12,15,20,24,30,36,48,60,72,96,100,120,144,200,240,288] # 移動平均期間(short/long)\n",
"PYRAMID_LIST = [1,2,3,4,5] # ピラミッディング(積み増し)回数\n",
"#-----------------------------------------------------------\n",
"\n",
"# パラメータ全組み合わせ(itertools.product : 直積)\n",
"df_params_pd = pd.DataFrame(list(itertools.product(SMA_LIST, SMA_LIST, PYRAMID_LIST,)),\n",
" columns=['short_sma', 'long_sma', 'pyramid'])\n",
"# short_sma < long_smaの組み合わせのみに絞り込み\n",
"df_params_pd = df_params_pd[(df_params_pd['short_sma'] < df_params_pd['long_sma'])]\n",
"# indexリセット\n",
"df_params_pd.reset_index(drop=True, inplace=True)\n",
"\n",
"# polars DataFrameコピー\n",
"df_params_pl = pl.from_pandas(df_params_pd)\n",
"df_params_pl2 = df_params_pl.clone()\n",
"\n",
"# パラメータ組み合わせ表示\n",
"display(df_params_pd)"
],
"metadata": {
"id": "hrmj3h-gd-Uu",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 424
},
"outputId": "181c73dd-5b80-48d2-b1ce-0891d1f42444"
},
"execution_count": 35,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
" short_sma long_sma pyramid\n",
"0 3 5 1\n",
"1 3 5 2\n",
"2 3 5 3\n",
"3 3 5 4\n",
"4 3 5 5\n",
".. ... ... ...\n",
"945 240 288 1\n",
"946 240 288 2\n",
"947 240 288 3\n",
"948 240 288 4\n",
"949 240 288 5\n",
"\n",
"[950 rows x 3 columns]"
],
"text/html": [
"\n",
" <div id=\"df-e36a27a8-637d-4b5b-bb6a-8f4fab0e44f4\">\n",
" <div class=\"colab-df-container\">\n",
" <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>short_sma</th>\n",
" <th>long_sma</th>\n",
" <th>pyramid</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3</td>\n",
" <td>5</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3</td>\n",
" <td>5</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3</td>\n",
" <td>5</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3</td>\n",
" <td>5</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3</td>\n",
" <td>5</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>945</th>\n",
" <td>240</td>\n",
" <td>288</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>946</th>\n",
" <td>240</td>\n",
" <td>288</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>947</th>\n",
" <td>240</td>\n",
" <td>288</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>948</th>\n",
" <td>240</td>\n",
" <td>288</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>949</th>\n",
" <td>240</td>\n",
" <td>288</td>\n",
" <td>5</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>950 rows × 3 columns</p>\n",
"</div>\n",
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-e36a27a8-637d-4b5b-bb6a-8f4fab0e44f4')\"\n",
" title=\"Convert this dataframe to an interactive table.\"\n",
" style=\"display:none;\">\n",
" \n",
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
" width=\"24px\">\n",
" <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
" <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
" </svg>\n",
" </button>\n",
" \n",
" <style>\n",
" .colab-df-container {\n",
" display:flex;\n",
" flex-wrap:wrap;\n",
" gap: 12px;\n",
" }\n",
"\n",
" .colab-df-convert {\n",
" background-color: #E8F0FE;\n",
" border: none;\n",
" border-radius: 50%;\n",
" cursor: pointer;\n",
" display: none;\n",
" fill: #1967D2;\n",
" height: 32px;\n",
" padding: 0 0 0 0;\n",
" width: 32px;\n",
" }\n",
"\n",
" .colab-df-convert:hover {\n",
" background-color: #E2EBFA;\n",
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
" fill: #174EA6;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert {\n",
" background-color: #3B4455;\n",
" fill: #D2E3FC;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert:hover {\n",
" background-color: #434B5C;\n",
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
" fill: #FFFFFF;\n",
" }\n",
" </style>\n",
"\n",
" <script>\n",
" const buttonEl =\n",
" document.querySelector('#df-e36a27a8-637d-4b5b-bb6a-8f4fab0e44f4 button.colab-df-convert');\n",
" buttonEl.style.display =\n",
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
"\n",
" async function convertToInteractive(key) {\n",
" const element = document.querySelector('#df-e36a27a8-637d-4b5b-bb6a-8f4fab0e44f4');\n",
" const dataTable =\n",
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
" [key], {});\n",
" if (!dataTable) return;\n",
"\n",
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
" + ' to learn more about interactive tables.';\n",
" element.innerHTML = '';\n",
" dataTable['output_type'] = 'display_data';\n",
" await google.colab.output.renderOutput(dataTable, element);\n",
" const docLink = document.createElement('div');\n",
" docLink.innerHTML = docLinkHtml;\n",
" element.appendChild(docLink);\n",
" }\n",
" </script>\n",
" </div>\n",
" </div>\n",
" "
]
},
"metadata": {}
}
]
},
{
"cell_type": "markdown",
"source": [
"## 【apply一括処理】\n",
"パラメータ組み合わせDataFrameにバックテスト関数を適用して総当りバックテストを行う"
],
"metadata": {
"id": "w50NIBOaMBLT"
}
},
{
"cell_type": "markdown",
"source": [
"### pandas"
],
"metadata": {
"id": "UCDNmQ2oMKgj"
}
},
{
"cell_type": "markdown",
"source": [
"#### 一括バックテスト実行"
],
"metadata": {
"id": "K-wHU70nORuh"
}
},
{
"cell_type": "code",
"source": [
"s = time.time()\n",
"\n",
"# パラメータ組み合わせにストラテジーを適用\n",
"result = df_params_pd.apply(lambda c: backtest_pandas(c['short_sma'], c['long_sma'], c['pyramid'],)['pnl'].values[-1], axis=1)\n",
"df_params_pd['result'] = result\n",
"df_params_pd = df_params_pd.sort_values('result') # result昇順ソート\n",
"\n",
"# テスト結果表示\n",
"display(df_params_pd)\n",
"\n",
"ret = round((time.time() - s) * 1000, 3)\n",
"print(f'[処理時間]: {ret} ms\\n')"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 458
},
"id": "CvzrpVlzvPd7",
"outputId": "5a5ac0e4-2564-4dc4-ec0b-9d2b7901f12a"
},
"execution_count": 36,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
" short_sma long_sma pyramid result\n",
"95 5 6 1 -302595.554868\n",
"96 5 6 2 -231074.405474\n",
"0 3 5 1 -207403.641505\n",
"270 10 12 1 -187248.424130\n",
"97 5 6 3 -179552.447503\n",
".. ... ... ... ...\n",
"672 30 288 3 30100.642723\n",
"585 24 96 1 30237.233825\n",
"671 30 288 2 31857.628859\n",
"795 60 200 1 38669.454905\n",
"260 6 240 1 40097.612877\n",
"\n",
"[950 rows x 4 columns]"
],
"text/html": [
"\n",
" <div id=\"df-2faaede5-5a33-462e-8946-d4dd2f27378a\">\n",
" <div class=\"colab-df-container\">\n",
" <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>short_sma</th>\n",
" <th>long_sma</th>\n",
" <th>pyramid</th>\n",
" <th>result</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>95</th>\n",
" <td>5</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>-302595.554868</td>\n",
" </tr>\n",
" <tr>\n",
" <th>96</th>\n",
" <td>5</td>\n",
" <td>6</td>\n",
" <td>2</td>\n",
" <td>-231074.405474</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3</td>\n",
" <td>5</td>\n",
" <td>1</td>\n",
" <td>-207403.641505</td>\n",
" </tr>\n",
" <tr>\n",
" <th>270</th>\n",
" <td>10</td>\n",
" <td>12</td>\n",
" <td>1</td>\n",
" <td>-187248.424130</td>\n",
" </tr>\n",
" <tr>\n",
" <th>97</th>\n",
" <td>5</td>\n",
" <td>6</td>\n",
" <td>3</td>\n",
" <td>-179552.447503</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>672</th>\n",
" <td>30</td>\n",
" <td>288</td>\n",
" <td>3</td>\n",
" <td>30100.642723</td>\n",
" </tr>\n",
" <tr>\n",
" <th>585</th>\n",
" <td>24</td>\n",
" <td>96</td>\n",
" <td>1</td>\n",
" <td>30237.233825</td>\n",
" </tr>\n",
" <tr>\n",
" <th>671</th>\n",
" <td>30</td>\n",
" <td>288</td>\n",
" <td>2</td>\n",
" <td>31857.628859</td>\n",
" </tr>\n",
" <tr>\n",
" <th>795</th>\n",
" <td>60</td>\n",
" <td>200</td>\n",
" <td>1</td>\n",
" <td>38669.454905</td>\n",
" </tr>\n",
" <tr>\n",
" <th>260</th>\n",
" <td>6</td>\n",
" <td>240</td>\n",
" <td>1</td>\n",
" <td>40097.612877</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>950 rows × 4 columns</p>\n",
"</div>\n",
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-2faaede5-5a33-462e-8946-d4dd2f27378a')\"\n",
" title=\"Convert this dataframe to an interactive table.\"\n",
" style=\"display:none;\">\n",
" \n",
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
" width=\"24px\">\n",
" <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
" <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
" </svg>\n",
" </button>\n",
" \n",
" <style>\n",
" .colab-df-container {\n",
" display:flex;\n",
" flex-wrap:wrap;\n",
" gap: 12px;\n",
" }\n",
"\n",
" .colab-df-convert {\n",
" background-color: #E8F0FE;\n",
" border: none;\n",
" border-radius: 50%;\n",
" cursor: pointer;\n",
" display: none;\n",
" fill: #1967D2;\n",
" height: 32px;\n",
" padding: 0 0 0 0;\n",
" width: 32px;\n",
" }\n",
"\n",
" .colab-df-convert:hover {\n",
" background-color: #E2EBFA;\n",
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
" fill: #174EA6;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert {\n",
" background-color: #3B4455;\n",
" fill: #D2E3FC;\n",
" }\n",
"\n",
" [theme=dark] .colab-df-convert:hover {\n",
" background-color: #434B5C;\n",
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
" fill: #FFFFFF;\n",
" }\n",
" </style>\n",
"\n",
" <script>\n",
" const buttonEl =\n",
" document.querySelector('#df-2faaede5-5a33-462e-8946-d4dd2f27378a button.colab-df-convert');\n",
" buttonEl.style.display =\n",
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
"\n",
" async function convertToInteractive(key) {\n",
" const element = document.querySelector('#df-2faaede5-5a33-462e-8946-d4dd2f27378a');\n",
" const dataTable =\n",
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
" [key], {});\n",
" if (!dataTable) return;\n",
"\n",
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
" + ' to learn more about interactive tables.';\n",
" element.innerHTML = '';\n",
" dataTable['output_type'] = 'display_data';\n",
" await google.colab.output.renderOutput(dataTable, element);\n",
" const docLink = document.createElement('div');\n",
" docLink.innerHTML = docLinkHtml;\n",
" element.appendChild(docLink);\n",
" }\n",
" </script>\n",
" </div>\n",
" </div>\n",
" "
]
},
"metadata": {}
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"[処理時間]: 57940.527 ms\n",
"\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"### polars"
],
"metadata": {
"id": "4LMe81_SMNJ7"
}
},
{
"cell_type": "markdown",
"source": [
"#### 一括バックテスト実行"
],
"metadata": {
"id": "9xRsOmLqOcIg"
}
},
{
"cell_type": "code",
"source": [
"s = time.time()\n",
"\n",
"# パラメータ組み合わせにストラテジーを適用\n",
"df_params_pl = (\n",
" df_params_pl.lazy()\n",
" .with_columns(\n",
" pl.struct(['short_sma', 'long_sma', 'pyramid',])\n",
" .apply(lambda c: backtest_polars(c['short_sma'], c['long_sma'], c['pyramid'],).get_column('pnl')[-1])\n",
" .alias('result')\n",
" )\n",
" .sort(pl.col('result')) # result昇順ソート\n",
" .collect()\n",
")\n",
"\n",
"# テスト結果表示\n",
"display(df_params_pl)\n",
"\n",
"ret = round((time.time() - s) * 1000, 3)\n",
"print(f'[処理時間]: {ret} ms\\n')"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 917
},
"id": "oJVh_TcsylGE",
"outputId": "43be4a28-5396-4f0e-afeb-b5c2e4a06707"
},
"execution_count": 37,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"shape: (950, 4)\n",
"┌───────────┬──────────┬─────────┬────────────────┐\n",
"│ short_sma ┆ long_sma ┆ pyramid ┆ result │\n",
"│ --- ┆ --- ┆ --- ┆ --- │\n",
"│ i64 ┆ i64 ┆ i64 ┆ f64 │\n",
"╞═══════════╪══════════╪═════════╪════════════════╡\n",
"│ 5 ┆ 6 ┆ 1 ┆ -302595.554868 │\n",
"│ 5 ┆ 6 ┆ 2 ┆ -231074.405474 │\n",
"│ 3 ┆ 5 ┆ 1 ┆ -207047.34376 │\n",
"│ 10 ┆ 12 ┆ 1 ┆ -187248.42413 │\n",
"│ ... ┆ ... ┆ ... ┆ ... │\n",
"│ 24 ┆ 96 ┆ 1 ┆ 30237.233825 │\n",
"│ 30 ┆ 288 ┆ 2 ┆ 31857.628859 │\n",
"│ 60 ┆ 200 ┆ 1 ┆ 38669.454905 │\n",
"│ 6 ┆ 240 ┆ 1 ┆ 40097.612877 │\n",
"└───────────┴──────────┴─────────┴────────────────┘"
],
"text/html": [
"<div>\n",
"<style>\n",
".pl-dataframe > thead > tr > th {\n",
" text-align: right;\n",
"}\n",
"</style>\n",
"\n",
"<table border=\"1\" class=\"dataframe pl-dataframe\">\n",
"<small>shape: (950, 4)</small>\n",
"<thead>\n",
"<tr>\n",
"<th>\n",
"short_sma\n",
"</th>\n",
"<th>\n",
"long_sma\n",
"</th>\n",
"<th>\n",
"pyramid\n",
"</th>\n",
"<th>\n",
"result\n",
"</th>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"i64\n",
"</td>\n",
"<td>\n",
"i64\n",
"</td>\n",
"<td>\n",
"i64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"</tr>\n",
"</thead>\n",
"<tbody>\n",
"<tr>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-302595.554868\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"-231074.405474\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-207047.34376\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"10\n",
"</td>\n",
"<td>\n",
"12\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-187248.42413\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"-179535.453592\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-179081.129635\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"10\n",
"</td>\n",
"<td>\n",
"12\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"-163407.166508\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"-159644.689164\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"4\n",
"</td>\n",
"<td>\n",
"-143044.280792\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"-137645.271559\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"10\n",
"</td>\n",
"<td>\n",
"12\n",
"</td>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"-134197.730481\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"12\n",
"</td>\n",
"<td>\n",
"15\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-128849.745035\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"10\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"28019.389825\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"30\n",
"</td>\n",
"<td>\n",
"288\n",
"</td>\n",
"<td>\n",
"4\n",
"</td>\n",
"<td>\n",
"28252.992011\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"100\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"28719.090037\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"30\n",
"</td>\n",
"<td>\n",
"288\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"28763.298202\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"60\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"28803.986696\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"72\n",
"</td>\n",
"<td>\n",
"240\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"28855.750183\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"96\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"29394.99565\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"30\n",
"</td>\n",
"<td>\n",
"288\n",
"</td>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"30100.642723\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"24\n",
"</td>\n",
"<td>\n",
"96\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"30237.233825\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"30\n",
"</td>\n",
"<td>\n",
"288\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"31857.628859\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"60\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"38669.454905\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"240\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"40097.612877\n",
"</td>\n",
"</tr>\n",
"</tbody>\n",
"</table>\n",
"</div>"
]
},
"metadata": {}
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"[処理時間]: 36584.938 ms\n",
"\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"#### (調整版)一括バックテスト実行"
],
"metadata": {
"id": "io5YfkKwOeEo"
}
},
{
"cell_type": "code",
"source": [
"s = time.time()\n",
"\n",
"# パラメータ組み合わせにストラテジーを適用\n",
"df_params_pl2 = (\n",
" df_params_pl2.lazy()\n",
" .with_columns(\n",
" pl.struct(['short_sma', 'long_sma', 'pyramid',])\n",
" .apply(lambda c: backtest_polars2(c['short_sma'], c['long_sma'], c['pyramid'],).get_column('pnl')[-1])\n",
" .alias('result')\n",
" )\n",
" .sort(pl.col('result')) # result昇順ソート\n",
" .collect()\n",
")\n",
"\n",
"# テスト結果表示\n",
"display(df_params_pl2)\n",
"\n",
"ret = round((time.time() - s) * 1000, 3)\n",
"print(f'[処理時間]: {ret} ms\\n')"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 917
},
"id": "r8yEU7EuGtTD",
"outputId": "f63fcaa9-cf8a-4efd-868f-cee92de4c01d"
},
"execution_count": 38,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"shape: (950, 4)\n",
"┌───────────┬──────────┬─────────┬────────────────┐\n",
"│ short_sma ┆ long_sma ┆ pyramid ┆ result │\n",
"│ --- ┆ --- ┆ --- ┆ --- │\n",
"│ i64 ┆ i64 ┆ i64 ┆ f64 │\n",
"╞═══════════╪══════════╪═════════╪════════════════╡\n",
"│ 5 ┆ 6 ┆ 1 ┆ -302595.554868 │\n",
"│ 5 ┆ 6 ┆ 2 ┆ -231074.405474 │\n",
"│ 3 ┆ 5 ┆ 1 ┆ -207047.34376 │\n",
"│ 10 ┆ 12 ┆ 1 ┆ -187248.42413 │\n",
"│ ... ┆ ... ┆ ... ┆ ... │\n",
"│ 24 ┆ 96 ┆ 1 ┆ 30237.233825 │\n",
"│ 30 ┆ 288 ┆ 2 ┆ 31857.628859 │\n",
"│ 60 ┆ 200 ┆ 1 ┆ 38669.454905 │\n",
"│ 6 ┆ 240 ┆ 1 ┆ 40097.612877 │\n",
"└───────────┴──────────┴─────────┴────────────────┘"
],
"text/html": [
"<div>\n",
"<style>\n",
".pl-dataframe > thead > tr > th {\n",
" text-align: right;\n",
"}\n",
"</style>\n",
"\n",
"<table border=\"1\" class=\"dataframe pl-dataframe\">\n",
"<small>shape: (950, 4)</small>\n",
"<thead>\n",
"<tr>\n",
"<th>\n",
"short_sma\n",
"</th>\n",
"<th>\n",
"long_sma\n",
"</th>\n",
"<th>\n",
"pyramid\n",
"</th>\n",
"<th>\n",
"result\n",
"</th>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"i64\n",
"</td>\n",
"<td>\n",
"i64\n",
"</td>\n",
"<td>\n",
"i64\n",
"</td>\n",
"<td>\n",
"f64\n",
"</td>\n",
"</tr>\n",
"</thead>\n",
"<tbody>\n",
"<tr>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-302595.554868\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"-231074.405474\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-207047.34376\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"10\n",
"</td>\n",
"<td>\n",
"12\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-187248.42413\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"-179535.453592\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-179081.129635\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"10\n",
"</td>\n",
"<td>\n",
"12\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"-163407.166508\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"-159644.689164\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"5\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"4\n",
"</td>\n",
"<td>\n",
"-143044.280792\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"-137645.271559\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"10\n",
"</td>\n",
"<td>\n",
"12\n",
"</td>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"-134197.730481\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"12\n",
"</td>\n",
"<td>\n",
"15\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"-128849.745035\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"<td>\n",
"...\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"10\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"28019.389825\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"30\n",
"</td>\n",
"<td>\n",
"288\n",
"</td>\n",
"<td>\n",
"4\n",
"</td>\n",
"<td>\n",
"28252.992011\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"100\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"28719.090037\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"30\n",
"</td>\n",
"<td>\n",
"288\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"28763.298202\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"60\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"28803.986696\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"72\n",
"</td>\n",
"<td>\n",
"240\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"28855.750183\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"96\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"29394.99565\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"30\n",
"</td>\n",
"<td>\n",
"288\n",
"</td>\n",
"<td>\n",
"3\n",
"</td>\n",
"<td>\n",
"30100.642723\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"24\n",
"</td>\n",
"<td>\n",
"96\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"30237.233825\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"30\n",
"</td>\n",
"<td>\n",
"288\n",
"</td>\n",
"<td>\n",
"2\n",
"</td>\n",
"<td>\n",
"31857.628859\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"60\n",
"</td>\n",
"<td>\n",
"200\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"38669.454905\n",
"</td>\n",
"</tr>\n",
"<tr>\n",
"<td>\n",
"6\n",
"</td>\n",
"<td>\n",
"240\n",
"</td>\n",
"<td>\n",
"1\n",
"</td>\n",
"<td>\n",
"40097.612877\n",
"</td>\n",
"</tr>\n",
"</tbody>\n",
"</table>\n",
"</div>"
]
},
"metadata": {}
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"[処理時間]: 35160.366 ms\n",
"\n"
]
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment