{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# ORDER Imbalance\n", "\n", "* introduced buyvolume and sellvolume on bar level.\n", "* calculated order imbalance ratio (buyvolume-sellvolume/totalvolume)\n", "* calculated on multiple timeframes\n", "* entry based on confluences imbalances\n", "\n", "## Note\n", "\n", "Order disbalance nepodminuje zmenu ceny (tzn. muze byt order disbalance na buy stranu, ale cena nemusi jit nahoru a naopak)\n", "Nicmene pokud je disbalance delsi a nedochazi ke zmene ceny - může to něco indikovat. \n", "Vytvořit si kumulativní disbalance - kumulátory, které se budou načítat, když se budou silné disbalance, bez změny ceny. Tento akumulátor se bude nabíjet disbalancí a vybíjet příslušnou změnou ceny." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "trades_df-BAC-2024-01-01T09_30_00-2024-05-14T16_00_00-CO4B7VPWUZF-100.parquet\n", "trades_df-BAC-2024-01-11T09:30:00-2024-01-12T16:00:00.parquet\n", "trades_df-SPY-2024-01-01T09:30:00-2024-05-14T16:00:00.parquet\n", "trades_df-BAC-2023-01-01T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\n", "ohlcv_df-BAC-2024-01-11T09:30:00-2024-01-12T16:00:00.parquet\n", "trades_df-BAC-2024-05-15T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\n", "ohlcv_df-BAC-2024-01-01T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\n", "ohlcv_df-SPY-2024-01-01T09:30:00-2024-05-14T16:00:00.parquet\n", "ohlcv_df-BAC-2024-01-01T09_30_00-2024-05-14T16_00_00-CO4B7VPWUZF-100.parquet\n", "ohlcv_df-BAC-2023-01-01T09_30_00-2024-05-25T16_00_00-47BCFOPUVWZ-100.parquet\n", "ohlcv_df-BAC-2023-01-01T09_30_00-2024-05-25T15_30_00-47BCFOPUVWZ-100.parquet\n" ] }, { "data": { "text/plain": [ "351" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from v2realbot.tools.loadbatch import load_batch\n", "from v2realbot.utils.utils import zoneNY\n", "import pandas as pd\n", "import numpy as np\n", "import vectorbtpro as vbt\n", "# from itables import init_notebook_mode, show\n", "import datetime\n", "from itertools import product\n", "from v2realbot.config import ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, DATA_DIR\n", "from lightweight_charts import JupyterChart, chart, Panel\n", "from IPython.display import display\n", "\n", "# init_notebook_mode(all_interactive=True)\n", "\n", "vbt.settings.set_theme(\"dark\")\n", "vbt.settings['plotting']['layout']['width'] = 1280\n", "vbt.settings.plotting.auto_rangebreaks = True\n", "# Set the option to display with pagination\n", "pd.set_option('display.notebook_repr_html', True)\n", "pd.set_option('display.max_rows', 10) # Number of rows per page\n", "\n", "# Define the market open and close times\n", "market_open = datetime.time(9, 30)\n", "market_close = datetime.time(16, 0)\n", "entry_window_opens = 1\n", "entry_window_closes = 370\n", "\n", "forced_exit_start = 380\n", "forced_exit_end = 390\n", "\n", "#LOAD FROM PARQUET\n", "#list all files is dir directory with parquet extension\n", "dir = DATA_DIR + \"/notebooks/\"\n", "import os\n", "files = [f for f in os.listdir(dir) if f.endswith(\".parquet\")]\n", "print('\\n'.join(map(str, files)))\n", "file_name = \"ohlcv_df-BAC-2023-01-01T09_30_00-2024-05-25T15_30_00-47BCFOPUVWZ-100.parquet\"\n", "ohlcv_df = pd.read_parquet(dir+file_name,engine='pyarrow')\n", "#filter ohlcv_df to certain date range (assuming datetime index)\n", "#ohlcv_df = ohlcv_df.loc[\"2024-02-12 9:30\":\"2024-02-14 16:00\"]\n", "\n", "#add vwap column to ohlcv_df\n", "#ohlcv_df[\"hlcc4\"] = (ohlcv_df[\"close\"] + ohlcv_df[\"high\"] + ohlcv_df[\"low\"] + ohlcv_df[\"close\"]) / 4\n", "\n", "basic_data = vbt.Data.from_data(vbt.symbol_dict({\"BAC\": ohlcv_df}), tz_convert=zoneNY)\n", "ohlcv_df= None\n", "basic_data.wrapper.index.normalize().nunique()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add resample function to custom columns" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "from vectorbtpro.utils.config import merge_dicts, Config, HybridConfig\n", "from vectorbtpro import _typing as tp\n", "from vectorbtpro.generic import nb as generic_nb\n", "\n", "_feature_config: tp.ClassVar[Config] = HybridConfig(\n", " {\n", " \"buyvolume\": dict(\n", " resample_func=lambda self, obj, resampler: obj.vbt.resample_apply(\n", " resampler,\n", " generic_nb.sum_reduce_nb,\n", " )\n", " ),\n", " \"sellvolume\": dict(\n", " resample_func=lambda self, obj, resampler: obj.vbt.resample_apply(\n", " resampler,\n", " generic_nb.sum_reduce_nb,\n", " )\n", " ),\n", " \"trades\": dict(\n", " resample_func=lambda self, obj, resampler: obj.vbt.resample_apply(\n", " resampler,\n", " generic_nb.sum_reduce_nb,\n", " )\n", " )\n", " }\n", ")\n", "\n", "basic_data._feature_config = _feature_config" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "DatetimeIndex: 4549772 entries, 2023-01-03 09:30:01-05:00 to 2024-05-24 15:59:59-04:00\n", "Data columns (total 10 columns):\n", " # Column Dtype \n", "--- ------ ----- \n", " 0 open float64 \n", " 1 high float64 \n", " 2 low float64 \n", " 3 close float64 \n", " 4 volume float64 \n", " 5 trades float64 \n", " 6 updated datetime64[ns, US/Eastern]\n", " 7 vwap float64 \n", " 8 buyvolume float64 \n", " 9 sellvolume float64 \n", "dtypes: datetime64[ns, US/Eastern](1), float64(9)\n", "memory usage: 381.8 MB\n" ] } ], "source": [ "basic_data.data[\"BAC\"].info()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "DatetimeIndex: 136526 entries, 2023-01-03 09:30:00-05:00 to 2024-05-24 15:59:00-04:00\n", "Data columns (total 9 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 open 136526 non-null float64\n", " 1 high 136526 non-null float64\n", " 2 low 136526 non-null float64\n", " 3 close 136526 non-null float64\n", " 4 volume 136526 non-null float64\n", " 5 vwap 136526 non-null float64\n", " 6 buyvolume 136526 non-null float64\n", " 7 trades 136526 non-null float64\n", " 8 sellvolume 136526 non-null float64\n", "dtypes: float64(9)\n", "memory usage: 10.4 MB\n" ] } ], "source": [ "t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','trades','sellvolume']].resample(\"1T\")\n", "t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "t1data.data[\"BAC\"].info()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "bbands = vbt.talib(\"BBANDS\").run(\n", " t1data.get(\"Close\"))\n", "\n", "\n", "supertrend = vbt.SUPERTREND.run(t1data.high, t1data.low, t1data.close, period=14, multiplier=3)\n", "#supertrend.output_names" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "time\n", "2024-02-12 09:30:00-05:00 1\n", "2024-02-12 09:31:00-05:00 1\n", "Name: (14, 3), dtype: int64" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "serka = supertrend.direction\n", "\n", "#a = serka.vbt.xloc[\"2024-02-12 09:30\":\"2024-02-12 09:32\"].obj\n", "\n", "a = serka.vbt.xloc[slice(\"2024-02-12 09:30\",\"2024-02-12 09:32\")].obj\n", " \n", "a\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
openhighlowclosevolumevwapbuyvolumetradessellvolume
time
2024-02-12 09:30:00-05:0033.00033.1332.99033.1150328563.033.033563280313.0282.014030.0
2024-02-12 09:31:00-05:0033.11533.1933.11533.180376896.033.15407615299.0213.020099.0
\n", "
" ], "text/plain": [ " open high low close volume \\\n", "time \n", "2024-02-12 09:30:00-05:00 33.000 33.13 32.990 33.1150 328563.0 \n", "2024-02-12 09:31:00-05:00 33.115 33.19 33.115 33.1803 76896.0 \n", "\n", " vwap buyvolume trades sellvolume \n", "time \n", "2024-02-12 09:30:00-05:00 33.033563 280313.0 282.0 14030.0 \n", "2024-02-12 09:31:00-05:00 33.154076 15299.0 213.0 20099.0 " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = t1data.data[\"BAC\"]\n", "\n", "df.vbt.xloc[\"2024-02-12 09:30\":\"2024-02-12 09:32\"].obj" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "time\n", "2024-02-12 09:30:00-05:00 NaN\n", "2024-02-12 09:31:00-05:00 NaN\n", "2024-02-12 09:32:00-05:00 NaN\n", "2024-02-12 09:33:00-05:00 NaN\n", "2024-02-12 09:34:00-05:00 NaN\n", " ... \n", "2024-02-14 09:56:00-05:00 32.931445\n", "2024-02-14 09:57:00-05:00 32.939706\n", "2024-02-14 09:58:00-05:00 32.939706\n", "2024-02-14 09:59:00-05:00 32.939706\n", "2024-02-14 10:00:00-05:00 32.939966\n", "Name: (14, 3), Length: 93, dtype: float64" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "supertrend.trend" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "pane1 = Panel(\n", " ohlcv=(t1data.data[\"BAC\"],), #(series, entries, exits, other_markers)\n", " histogram=[], # [(series, name, \"rgba(53, 94, 59, 0.6), opacity\")]\n", " right=[#(bbands,), #[(series, name, entries, exits, other_markers)]\n", " (supertrend.trend,\"STtrend\"),\n", " (supertrend.long,\"STlong\"),\n", " (supertrend.short,\"STshort\")\n", " ],\n", " left = [(supertrend.direction,\"STdirection\")],\n", " # right=[(bbands.upperband, \"upperband\",),\n", " # (bbands.lowerband, \"lowerband\",),\n", " # (bbands.middleband, \"middleband\",)\n", " # ], #[(series, name, entries, exits, other_markers)]\n", " middle1=[],\n", " middle2=[],\n", ")\n", "\n", "pane2 = Panel(\n", " ohlcv=(t1data.data[\"BAC\"],), #(series, entries, exits, other_markers)\n", " histogram=[], # [(series, name, \"rgba(53, 94, 59, 0.6), opacity\")]\n", " right=[(bbands,), #[(series, name, entries, exits, other_markers)]\n", " # (supertrend.trend,\"STtrend\"),\n", " # (supertrend.long,\"STlong\"),\n", " # (supertrend.short,\"STshort\")\n", " ],\n", " # left = [(supertrend.direction,\"STdirection\")],\n", " # right=[(bbands.upperband, \"upperband\",),\n", " # (bbands.lowerband, \"lowerband\",),\n", " # (bbands.middleband, \"middleband\",)\n", " # ], #[(series, name, entries, exits, other_markers)]\n", " middle1=[],\n", " middle2=[],\n", ")\n", "\n", "ch = chart([pane1, pane2], sync=True, size=\"s\", xloc=slice(\"2024-02-12 09:30\",\"2024-03-12\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "buyvolume = t1data.data[\"BAC\"].buyvolume\n", "sellvolume = t1data.data[\"BAC\"].sellvolume\n", "totalvolume = buyvolume + sellvolume\n", "\n", "#adjust to minimal value to avoid division by zero\n", "sellvolume_adjusted = sellvolume.replace(0, 1e-10)\n", "oibratio = buyvolume / sellvolume\n", "\n", "#cumulative order flow (net difference)\n", "cof = buyvolume - sellvolume\n", "\n", "# Calculate the order imbalance (net differene) normalize the order imbalance by calculating the difference between buy and sell volumes and then scaling it by the total volume.\n", "order_imbalance = cof / totalvolume\n", "order_imbalance = order_imbalance.fillna(0) #nan nahradime 0\n", "\n", "order_imbalance_allvolume = cof / t1data.data[\"BAC\"].volume\n", "\n", "order_imbalance_sma = vbt.indicator(\"talib:EMA\").run(order_imbalance, timeperiod=5)\n", "short_signals = order_imbalance.vbt < -0.5\n", "#short_entries = oibratio.vbt < 0.01\n", "short_signals.value_counts()\n", "short_signals.name = \"short_entries\"\n", "#.fillna(False)\n", "short_exits = short_signals.shift(-2).fillna(False).astype(bool)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pane1 = Panel(\n", " ohlcv=(t1data.data[\"BAC\"],), #(series, entries, exits, other_markers)\n", " histogram=[(order_imbalance_allvolume, \"oib_allvolume\", \"rgba(53, 94, 59, 0.6)\",0.5),\n", " (t1data.data[\"BAC\"].trades, \"trades\",None,0.4),\n", " ], # [(series, name, \"rgba(53, 94, 59, 0.6)\", opacity)]\n", " # right=[\n", " # (supertrend.trend,\"STtrend\"),\n", " # (supertrend.long,\"STlong\"),\n", " # (supertrend.short,\"STshort\")\n", " # ],\n", " # left = [(supertrend.direction,\"STdirection\")],\n", " # right=[(bbands.upperband, \"upperband\",),\n", " # (bbands.lowerband, \"lowerband\",),\n", " # (bbands.middleband, \"middleband\",)\n", " # ], #[(series, name, entries, exits, other_markers)]\n", " middle1=[],\n", " middle2=[],\n", ")\n", "\n", "pane2 = Panel(\n", " ohlcv=(basic_data.data[\"BAC\"],), #(series, entries, exits, other_markers)\n", " left=[(basic_data.data[\"BAC\"].trades, \"trades\")],\n", " histogram=[(basic_data.data[\"BAC\"].trades, \"trades_hist\", \"white\", 0.5)], #\"rgba(53, 94, 59, 0.6)\"\n", " # ], # [(series, name, \"rgba(53, 94, 59, 0.6)\")]\n", " # right=[\n", " # (supertrend.trend,\"STtrend\"),\n", " # (supertrend.long,\"STlong\"),\n", " # (supertrend.short,\"STshort\")\n", " # ],\n", " # left = [(supertrend.direction,\"STdirection\")],\n", " # right=[(bbands.upperband, \"upperband\",),\n", " # (bbands.lowerband, \"lowerband\",),\n", " # (bbands.middleband, \"middleband\",)\n", " # ], #[(series, name, entries, exits, other_markers)]\n", " middle1=[],\n", " middle2=[],\n", ")\n", "\n", "\n", "ch = chart([pane1, pane2], size=\"m\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##z tohoto si udelat plot funkci (i pro entries,exits)\n", "#t1data = t1data[[\"open\", \"high\", \"low\", \"close\", \"volume\"]]\n", "chart = JupyterChart(width=1000, height=600, inner_width=1, inner_height=0.5, leftScale=True)\n", "#set resolution\n", "t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")\n", "t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "chart.set(t1data.data[\"BAC\"])\n", "line_vwap = chart.create_line(name=\"vwap\")#, color=\"blue\")\n", "line_vwap.set(t1data.vwap)\n", "\n", "\n", "chart.topbar.textbox(\"title\",\"Nadpis\")\n", "chart2 = chart.create_subchart(position='right', width=1, height=0.5, sync=True, leftScale=True)\n", "t2data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"5T\")\n", "t2data = t2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "\n", "\n", "#5min close realigned to 1T\n", "close_realigned = t2data.close.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n", "#close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n", "line1 = chart.create_line(name=\"5minclose\")#, color=\"green\")\n", "line1.set(close_realigned)\n", "\n", "#sma z realigned dat\n", "sma_tp = 20\n", "sma_t2 = vbt.indicator(\"talib:EMA\").run(close_realigned, timeperiod=sma_tp)\n", "smaline = chart.create_line(name=f\"sma{sma_tp}\")#, color=\"blue\")\n", "smaline.set(sma_t2)\n", "\n", "\n", "#sma z puvodnich resamplovanych dat plus navic realign, melo by byt stejne \n", "sma_real = vbt.indicator(\"talib:EMA\").run(t2data.close, timeperiod=sma_tp)\n", "sma_real_value = sma_real.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "sma_real_value = sma_real_value[sma_real_value.index.dayofweek < 5]\n", "smaline_real = chart.create_line(name=f\"smareal{sma_tp}\", color=\"yellow\")\n", "smaline_real.set(sma_real_value)\n", "\n", "#resample 15T\n", "t15data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"15T\")\n", "t15data = t15data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "\n", "#5min close realigned to 1T\n", "close_15realigned = t15data.close.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "close_15realigned = close_15realigned[close_15realigned.index.dayofweek < 5]\n", "#close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n", "line2 = chart.create_line(name=\"15minclose\")#, color=\"pink\")\n", "line2.set(close_15realigned)\n", "\n", "\n", "chart.legend(True)\n", "hst = chart2.create_histogram(name=\"buyvolume\", color=\"rgba(53, 94, 59, 0.6)\") #green transparent\n", "hst1 = chart2.create_histogram(name=\"sellvolume\", color=\"rgba(165, 42, 42, 0.6)\") #red transparent\n", "hst.set(t1data.data[\"BAC\"])\n", "hst1.set(t1data.data[\"BAC\"])\n", "line2 = chart2.create_line(name=\"5minclose\")#, color=\"green\")\n", "line2.set(close_realigned)\n", "\n", "lineoib = chart2.create_line(name=\"oib\", priceScaleId=\"left\") #color=\"violet\", \n", "#lineoib.scale(0.7,0)\n", "lineoib.set(order_imbalance_allvolume)\n", "\n", "lineoib_sma = chart2.create_line(name=\"oibsma5\", priceScaleId=\"left\") #, color=\"blue\", \n", "lineoib_sma.set(order_imbalance_sma)\n", "\n", "chart.fit()\n", "chart2.legend(True)\n", "#\n", "line2.markers_set(short_signals, \"entries\")\n", "# TODO jelikoz se davaji do jednoho pole je treba zajistit spravne sortovani\n", "# domyslet jak to pojmout iterativni doplnovani markeru\n", "line2.markers_set(short_exits, \"exits\")\n", "\n", "\n", "chart2.fit()\n", "chart.load()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "short_signals.info()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#vbt.IF.list_indicators(\"*ma\")\n", "vbt.phelp(vbt.indicator(\"talib:EMA\").run)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sma = vbt.indicator(\"talib:EMA\").run(t1data.close, timeperiod=20)\n", "sma.real.info()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rr = vbt.RSI.run(t1data.close)\n", "type(rr)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "buyvolume = t1data.data[\"BAC\"].buyvolume\n", "sellvolume = t1data.data[\"BAC\"].sellvolume\n", "totalvolume = buyvolume + sellvolume\n", "\n", "#adjust to minimal value to avoid division by zero\n", "sellvolume_adjusted = sellvolume.replace(0, 1e-10)\n", "oibratio = buyvolume / sellvolume\n", "\n", "#cumulative order flow (net difference)\n", "cof = buyvolume - sellvolume\n", "\n", "# Calculate the order imbalance (net differene) normalize the order imbalance by calculating the difference between buy and sell volumes and then scaling it by the total volume.\n", "order_imbalance = cof / totalvolume\n", "order_imbalance = order_imbalance.fillna(0) #nan nahradime 0\n", "\n", "order_imbalance_allvolume = cof / t1data.data[\"BAC\"].volume" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "order_imbalance_sma = vbt.indicator(\"talib:EMA\").run(order_imbalance, timeperiod=5)\n", "short_signals = order_imbalance.vbt < -0.5\n", "#short_entries = oibratio.vbt < 0.01\n", "short_signals.value_counts()\n", "short_signals.name = \"short_entries\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "short_signals.info()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "short_signals" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "order_imbalance.fillna(0)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "order_imbalance.vbt.plot()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "order_imbalance" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "chartN = JupyterChart(width=500, height=300, inner_width=1, inner_height=0.3, leftScale=True)\n", "t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")\n", "t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "chartN.set(t1data.data[\"BAC\"])\n", "line_sma = chartN.create_line(name=\"sma\", priceScaleId=\"right\")#, color=\"blue\")\n", "line_sma.set(sma)\n", "# line_sma.markers_set(short_signals, \"entries\")\n", "# line_sma.markers_set(short_exits, \"exits\")\n", "# hst = chartN.create_histogram(name=\"oivol\")\n", "# hst.set(order_imbalance_allvolume)\n", "# chartN.legend(True)\n", "# chartN.fit()\n", "\n", "# subchart = chartN.create_subchart(position='right', width=1, height=0.5, sync=False, leftScale=True)\n", "# # subchart.set(t1data.data[\"BAC\"])\n", "# line_sma1 = subchart.create_line(name=\"smao\", priceScaleId=\"left\")#, color=\"blue\")\n", "# line_sma1.set(sma)\n", "# # line_sma1.markers_set(short_signals, \"entries\")\n", "# # line_sma1.markers_set(short_exits, \"exits\")\n", "# hsto = subchart.create_histogram(name=\"oivolo\")\n", "# hsto.set(order_imbalance_sma)\n", "\n", "chart2 = chartN.create_subchart(position='left', width=1, height=0.5, sync=True, leftScale=True, toolbox=True)\n", "# hst = chart2.create_histogram(name=\"buyvolume\", color=\"rgba(53, 94, 59, 0.6)\") #green transparent\n", "# hst1 = chart2.create_histogram(name=\"sellvolume\", color=\"rgba(165, 42, 42, 0.6)\") #red transparent\n", "# hst.set(t1data.data[\"BAC\"])\n", "# hst1.set(t1data.data[\"BAC\"])\n", "line2 = chart2.create_line(name=\"sma\")#, color=\"green\")\n", "line2.set(sma)\n", "chart2.topbar.textbox(\"title\",\"Nadpis\")\n", "# chartN.topbar.textbox(\"title\",\"NadpisT\")\n", "\n", "# subchart.legend(True)\n", "# subchart.fit()\n", "chartN.load()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##z tohoto si udelat plot funkci (i pro entries,exits)\n", "#t1data = t1data[[\"open\", \"high\", \"low\", \"close\", \"volume\"]]\n", "chart = JupyterChart(width=1000, height=600, inner_width=1, inner_height=0.5, leftScale=True)\n", "#set resolution\n", "t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")\n", "t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "chart.set(t1data.data[\"BAC\"])\n", "line_vwap = chart.create_line(name=\"vwap\")#, color=\"blue\")\n", "line_vwap.set(t1data.vwap)\n", "\n", "\n", "chart.topbar.textbox(\"title\",\"Nadpis\")\n", "chart2 = chart.create_subchart(position='right', width=1, height=0.5, sync=True, leftScale=True)\n", "t2data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"5T\")\n", "t2data = t2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "\n", "\n", "#5min close realigned to 1T\n", "close_realigned = t2data.close.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n", "#close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n", "line1 = chart.create_line(name=\"5minclose\")#, color=\"green\")\n", "line1.set(close_realigned)\n", "\n", "#sma z realigned dat\n", "sma_tp = 20\n", "sma_t2 = vbt.indicator(\"talib:EMA\").run(close_realigned, timeperiod=sma_tp)\n", "smaline = chart.create_line(name=f\"sma{sma_tp}\")#, color=\"blue\")\n", "smaline.set(sma_t2)\n", "\n", "\n", "#sma z puvodnich resamplovanych dat plus navic realign, melo by byt stejne \n", "sma_real = vbt.indicator(\"talib:EMA\").run(t2data.close, timeperiod=sma_tp)\n", "sma_real_value = sma_real.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "sma_real_value = sma_real_value[sma_real_value.index.dayofweek < 5]\n", "smaline_real = chart.create_line(name=f\"smareal{sma_tp}\", color=\"yellow\")\n", "smaline_real.set(sma_real_value)\n", "\n", "#resample 15T\n", "t15data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"15T\")\n", "t15data = t15data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "\n", "#5min close realigned to 1T\n", "close_15realigned = t15data.close.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "close_15realigned = close_15realigned[close_15realigned.index.dayofweek < 5]\n", "#close_realigned = close_realigned[close_realigned.index.dayofweek < 5]\n", "line2 = chart.create_line(name=\"15minclose\")#, color=\"pink\")\n", "line2.set(close_15realigned)\n", "\n", "\n", "chart.legend(True)\n", "hst = chart2.create_histogram(name=\"buyvolume\", color=\"rgba(53, 94, 59, 0.6)\") #green transparent\n", "hst1 = chart2.create_histogram(name=\"sellvolume\", color=\"rgba(165, 42, 42, 0.6)\") #red transparent\n", "hst.set(t1data.data[\"BAC\"])\n", "hst1.set(t1data.data[\"BAC\"])\n", "line2 = chart2.create_line(name=\"5minclose\")#, color=\"green\")\n", "line2.set(close_realigned)\n", "\n", "lineoib = chart2.create_line(name=\"oib\", priceScaleId=\"left\") #color=\"violet\", \n", "#lineoib.scale(0.7,0)\n", "lineoib.set(order_imbalance_allvolume)\n", "\n", "lineoib_sma = chart2.create_line(name=\"oibsma5\", priceScaleId=\"left\") #, color=\"blue\", \n", "lineoib_sma.set(order_imbalance_sma)\n", "\n", "chart.fit()\n", "chart2.legend(True)\n", "#\n", "line2.markers_set(short_signals, \"entries\")\n", "# TODO jelikoz se davaji do jednoho pole je treba zajistit spravne sortovani\n", "# domyslet jak to pojmout iterativni doplnovani markeru\n", "line2.markers_set(short_exits, \"exits\")\n", "\n", "\n", "chart2.fit()\n", "chart.load()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sma.info()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#priminds list (same Y as price), secinds list (secondary Y napr. rsi), close, voluminds (volume based) list\n", "def plot_2y_close(priminds, secinds, close, volumeinds, ohlcv=None):\n", " fig = vbt.make_subplots(rows=2, cols=1, shared_xaxes=True, \n", " specs=[[{\"secondary_y\": True}], [{\"secondary_y\": False}]], \n", " vertical_spacing=0.02, subplot_titles=(\"Price and Indicators\", \"Volume\"))\n", "\n", " if ohlcv is not None:\n", " ohlcv.vbt.ohlcv.plot(fig=fig, add_trace_kwargs=dict(row=1, col=1))\n", "\n", " # Plotting the close price\n", " close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False,row=1, col=1), trace_kwargs=dict(line=dict(color=\"blue\")))\n", " \n", " # Plotting primary indicators on the first row\n", " for ind in priminds:\n", " if isinstance(ind, pd.Series):\n", " #if series has no name, make the name same as the variable name\n", " \n", " ind = ind.vbt\n", " ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n", " \n", " # Plotting secondary indicators on the first row\n", " for ind in secinds:\n", " #ind = ind.rename(str(ind.name))\n", " if isinstance(ind, pd.Series):\n", " ind = ind.vbt\n", " ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1), trace_kwargs=dict(line=dict(color=\"rgba(255, 0, 0, 0.4)\")))\n", " \n", " for indvolume in volumeinds:\n", " # Plotting the volume on the second row\n", " indvolume.rename(str(indvolume.name)).vbt.barplot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=2, col=1))\n", " #vbt.Bar(indvolume, fig=fig, add_trace_kwargs=dict(secondary_y=False, row=2, col=1))\n", " \n", " return fig\n", "\n", "fig = plot_2y_close([sma], [order_imbalance.rename(\"order_imbalance_norm\"),order_imbalance_sma.real.rename(\"oib_sma\")], t1data.close, [t1data.data[\"BAC\"].buyvolume, t1data.data[\"BAC\"].sellvolume, t1data.volume], t1data.data[\"BAC\"])\n", "fig.update_yaxes(range=[33,34], secondary_y=False, row=1, col=1) #update y axis range\n", "fig.update_yaxes(range=[-1,1], secondary_y=True, row=1, col=1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "t0data = basic_data\n", "t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"1T\")\n", "t2data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"15T\")\n", "t3data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap']].resample(\"30T\")\n", "t4data = basic_data[['open', 'high', 'low', 'close', 'volume', 'vwap']].resample(\"D\").dropna()\n", "\n", "t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "t2data = t2data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "t3data = t3data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "\n", "#30min data to daily\n", "# t4data = t3data.resample(\"D\").dropna()\n", "\n", "#t4data = t4data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n", "#m1data.data[\"SPY\"].info()\n", "\n", "#m1data.data[\"SPY\"].vbt.ohlcv.plot()\n", "#h2data.data[\"SPY\"].vbt.ohlcv.plot()\n", "#ddata.data[\"SPY\"]\n", "t2data.data[\"BAC\"].vbt.ohlcv.plot().show()\n", "\n", "\n", "#t4data.data[\"BAC\"]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t2data.close\n", "\n", "#in df remove rows with nan\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#realign na 1T = t1data + oriznout main session\n", "t2data_vwap = t2data.vwap.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "t3data_vwap = t3data.vwap.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "t4data_vwap = t4data.vwap.vbt.realign_closing(\"1T\").dropna()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t2data_vwap" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def plot_2y_close(priminds, secinds, close):\n", " fig = vbt.make_subplots(rows=1, cols=1, shared_xaxes=True, specs=[[{\"secondary_y\": True}]], vertical_spacing=0.02, subplot_titles=(\"MOM\", \"Price\" ))\n", " close.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False), trace_kwargs=dict(line=dict(color=\"blue\")))\n", " for ind in priminds:\n", " if isinstance(ind, pd.Series):\n", " ind = ind.vbt\n", " ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False))\n", " for ind in secinds:\n", " if isinstance(ind, pd.Series):\n", " ind = ind.vbt\n", " ind.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))\n", " return fig" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t4data.clos.vbt \n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "obvind = vbt.indicator.obv.run(t1data.close, t1data.volume)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t1_lengtgh = 15\n", "t2_length = 15\n", "t3_length = 15\n", "t4_length = 5\n", "t1_th = 0.1\n", "t2_th = 0.1\n", "t3_th = 0.1\n", "t4_th = 0.1\n", "\n", "\n", "\n", "#minute\n", "t1slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t1data.close, timeperiod=t1_lengtgh) # -0.09, 0.09\n", "t2slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t2data.vwap, timeperiod=t2_length) # -0.08 , 0.079\n", "t3slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t3data.vwap, timeperiod=t3_length) # -0.08, 0.08\n", "#daily\n", "t4slope = vbt.indicator(\"talib:LINEARREG_SLOPE \").run(t4data.vwap, timeperiod=t4_length) # -0.1, 0.09\n", "\n", "plot_2y_close(priminds=[], secinds=[t1slope, t2slope, t3slope, t4slope], close=t1data.close).show()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#thirtymin_slope = thirtymin_slope.real.rename(\"30min\") #timto se prejmenuje real na 30min\n", "t3slope = t3slope.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "##filter daily_slope_to_compare to only monday to friday\n", "t3slope = t3slope[t3slope.index.dayofweek < 5]\n", "\n", "#t3slope.info()\n", "\n", "t2slope = t2slope.real.vbt.realign_closing(\"1T\").between_time('09:30', '16:00').dropna()\n", "##filter daily_slope_to_compare to only monday to friday\n", "t2slope = t2slope[t2slope.index.dayofweek < 5]\n", "\n", "t2slope.info()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "oibratio" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "#\n", "short_signals = order_imbalance.vbt < -0.3\n", "#short_entries = oibratio.vbt < 0.01\n", "short_signals.value_counts()\n", "\n", "long_signals = order_imbalance.vbt > 0.3\n", "#entries = oibratio.vbt > 10\n", "long_signals.value_counts()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig = vbt.make_subplots(rows=3, cols=1, shared_xaxes=True, \n", " specs=[[{\"secondary_y\": True}], [{\"secondary_y\": True}], [{\"secondary_y\": False}]], \n", " vertical_spacing=0.02, subplot_titles=(\"Price and Indicators\", \"Volume\"))\n", "t1data.data[\"BAC\"].vbt.ohlcv.plot(fig=fig, add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n", "#oibratio.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n", "order_imbalance.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True, row=1, col=1))\n", "long_signals.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"LONGS\",\n", " line=dict(color=\"#ffe476\"),\n", " marker=dict(color=\"limegreen\"),\n", " fill=None,\n", " connectgaps=True,\n", " ), add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n", "\n", "short_signals.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"SHORTS\",\n", " line=dict(color=\"#ffe476\"),\n", " marker=dict(color=\"red\"),\n", " fill=None,\n", " connectgaps=True,\n", " ), add_trace_kwargs=dict(secondary_y=False, row=1, col=1))\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# thirtymin_slope_to_compare.vbt.xloc[\"04-16-2024\"].get()\n", "thirty_down_signal.vbt.xloc[\"04-16-2024\"].get()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#short_signal = t1slope.real_below(t1_th) & t2slope.real_below(t2_th) & t3slope.real_below(t3_th) & t4slope.real_below(t4_th)\n", "#long_signal = t1slope.real_above(t1_th) & t2slope.real_above(t2_th) & t3slope.real_above(t3_th) & t4slope.real_above(t4_th)\n", "\n", "#test na daily s reversem crossed 0\n", "short_signal = t2slope.vbt < -0.01 & t3slope.vbt < -0.01 #min value of threshold\n", "long_signal = t2slope.vbt > 0.01 & t3slope.vbt > 0.01 #min\n", "\n", "# thirty_up_signal = t3slope.vbt.crossed_above(0.01)\n", "# thirty_down_signal = t3slope.vbt.crossed_below(-0.01)\n", "\n", "fig = plot_2y_close(priminds=[], secinds=[t3slope], close=t1data.close)\n", "#short_signal.vbt.signals.plot_as_entries(basic_data.close, fig=fig)\n", "\n", "short_signal.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"SHORTS\",\n", " line=dict(color=\"#ffe476\"),\n", " marker=dict(color=\"red\", symbol=\"triangle-down\"),\n", " fill=None,\n", " connectgaps=True,\n", " ))\n", "long_signal.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"LONGS\",\n", " line=dict(color=\"#ffe476\"),\n", " marker=dict(color=\"limegreen\"),\n", " fill=None,\n", " connectgaps=True,\n", " ))\n", "\n", "# thirty_down_signal.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"DOWN30\",\n", "# line=dict(color=\"#ffe476\"),\n", "# marker=dict(color=\"yellow\", symbol=\"triangle-down\"),\n", "# fill=None,\n", "# connectgaps=True,\n", "# ))\n", "# thirty_up_signal.vbt.signals.plot_as_entries(t1data.close, fig=fig, trace_kwargs=dict(name=\"UP30\",\n", "# line=dict(color=\"#ffe476\"),\n", "# marker=dict(color=\"grey\"),\n", "# fill=None,\n", "# connectgaps=True,\n", "# ))\n", "\n", "# thirtymin_slope_to_compare.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True), trace_kwargs=dict(name=\"30min slope\",\n", "# line=dict(color=\"yellow\"), \n", "# fill=None,\n", "# connectgaps=True,\n", "# ))\n", "\n", "fig.show()\n", "# print(\"short signal\")\n", "# print(short_signal.value_counts())\n", "\n", "#forced_exit = pd.Series(False, index=close.index)\n", "forced_exit = basic_data.symbol_wrapper.fill(False)\n", "#entry_window_open = pd.Series(False, index=close.index)\n", "entry_window_open= basic_data.symbol_wrapper.fill(False)\n", "\n", "# Calculate the time difference in minutes from market open for each timestamp\n", "elapsed_min_from_open = (forced_exit.index.hour - market_open.hour) * 60 + (forced_exit.index.minute - market_open.minute)\n", "\n", "entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n", "\n", "#print(entry_window_open.value_counts())\n", "\n", "forced_exit[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True\n", "short_entries = (short_signal & entry_window_open)\n", "short_exits = forced_exit\n", "\n", "entries = (long_signal & entry_window_open)\n", "exits = forced_exit\n", "#long_entries.info()\n", "#number of trues and falses in long_entries\n", "# print(short_exits.value_counts())\n", "# print(short_entries.value_counts())\n", "\n", "#fig = plot_2y_close([],[momshort, rocp], close)\n", "#short_signal.vbt.signals.plot_as_entries(close, fig=fig, add_trace_kwargs=dict(secondary_y=False))\n", "#print(sl_stop)\n", "#short_entries=short_entries, short_exits=short_exits,\n", "# pf = vbt.Portfolio.from_signals(close=basic_data, entries=short_entries, exits=exits, tsl_stop=0.005, tp_stop = 0.05, fees=0.0167/100, freq=\"1s\") #sl_stop=sl_stop, tp_stop = sl_stop,\n", "\n", "# pf.stats()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "forced_exit = t1data.symbol_wrapper.fill(False)\n", "#entry_window_open = pd.Series(False, index=close.index)\n", "entry_window_open= t1data.symbol_wrapper.fill(False)\n", "\n", "# Calculate the time difference in minutes from market open for each timestamp\n", "elapsed_min_from_open = (forced_exit.index.hour - market_open.hour) * 60 + (forced_exit.index.minute - market_open.minute)\n", "\n", "entry_window_open[(elapsed_min_from_open >= entry_window_opens) & (elapsed_min_from_open < entry_window_closes)] = True\n", "\n", "#print(entry_window_open.value_counts())\n", "\n", "forced_exit[(elapsed_min_from_open >= forced_exit_start) & (elapsed_min_from_open < forced_exit_end)] = True\n", "short_entries = (short_signals & entry_window_open)\n", "short_exits = forced_exit\n", "\n", "entries = (long_signals & entry_window_open)\n", "exits = forced_exit\n", "\n", "pf = vbt.Portfolio.from_signals(close=t1data, entries=entries, exits=exits, short_entries=short_entries, short_exits=exits,\n", "td_stop=2, time_delta_format=\"rows\",\n", "tsl_stop=0.005, tp_stop = 0.005, fees=0.0167/100)#, freq=\"1s\") #sl_stop=sl_stop, tp_stop = sl_stop,\n", "\n", "pf.stats()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pf.plot()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pf.get_drawdowns().records_readable" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pf.orders.records_readable" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.11" } }, "nbformat": 4, "nbformat_minor": 2 }