965 lines
38 KiB
Plaintext
965 lines
38 KiB
Plaintext
{
|
|
"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": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"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 as chartp, 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-03-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"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Add resample function to custom columns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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",
|
|
" }\n",
|
|
")\n",
|
|
"\n",
|
|
"basic_data._feature_config = _feature_config"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#asic_data.stats()\n",
|
|
"basic_data.wrapper.index.normalize().nunique()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#basic_data.ohlcv.plot()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"second_data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']]\n",
|
|
"t1data = basic_data[['open', 'high', 'low', 'close', 'volume','vwap','buyvolume','sellvolume']].resample(\"1T\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"t1data = t1data.transform(lambda df: df.between_time('09:30', '16:00').dropna())\n",
|
|
"#t1data = t1data.xloc[\"2024-02-12 9:30\":\"2024-02-14 16:00\"]\n",
|
|
"basic_data = t1data"
|
|
]
|
|
},
|
|
{
|
|
"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": [
|
|
"##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
|
|
}
|