{ "cells": [ { "cell_type": "markdown", "id": "16f4ed9b-5a03-4225-b54c-9a8be3f32cfa", "metadata": {}, "source": [ "# Patterns and projections" ] }, { "cell_type": "markdown", "id": "09993824-ddc7-4e30-8bb6-a1e86f6bf78c", "metadata": {}, "source": [ "## Patterns" ] }, { "cell_type": "code", "execution_count": null, "id": "f28adb62-732c-4fdb-90eb-553650314736", "metadata": {}, "outputs": [], "source": [ "from vectorbtpro import *\n", "# whats_imported()\n", "\n", "vbt.settings.set_theme(\"dark\")" ] }, { "cell_type": "code", "execution_count": null, "id": "b2745757-3cce-42f9-ac4c-2efe41ec4d20", "metadata": {}, "outputs": [], "source": [ "data = vbt.BinanceData.pull(\n", " \"BTCUSDT\", \n", " start=\"2020-06-01 UTC\", \n", " end=\"2022-06-01 UTC\"\n", ")\n", "data.plot().show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "8d28352b-b24d-4d9e-b2ff-8b893dc09da7", "metadata": {}, "outputs": [], "source": [ "data_window = data.loc[\"2021-09-25\":\"2021-11-25\"]\n", "data_window.plot(plot_volume=False).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "7dfcdf27-18b3-4fe1-bcc1-8ebf681827e7", "metadata": {}, "outputs": [], "source": [ "price_window = data_window.hlc3\n", "price_window.vbt.plot().show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "a65950da-0df5-4371-8b50-54ded8fbfa7f", "metadata": {}, "outputs": [], "source": [ "pattern = np.array([1, 2, 3, 2, 3, 2])\n", "pd.Series(pattern).vbt.plot().show_svg()" ] }, { "cell_type": "markdown", "id": "ec71f516-e9ca-4238-befd-c2a30b9018ce", "metadata": {}, "source": [ "### Interpolation" ] }, { "cell_type": "markdown", "id": "9b36945d-dc5b-4cc1-a53b-683ac294a657", "metadata": {}, "source": [ "#### Linear" ] }, { "cell_type": "code", "execution_count": null, "id": "3b2eceec-da77-4cf5-bb5b-2355fdff5db2", "metadata": {}, "outputs": [], "source": [ "resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, 10, vbt.enums.InterpMode.Linear\n", ")\n", "resized_pattern" ] }, { "cell_type": "code", "execution_count": null, "id": "56ed8dd0-0192-4242-9a86-906c1cdf9982", "metadata": {}, "outputs": [], "source": [ "def plot_linear(n):\n", " resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, n, vbt.enums.InterpMode.Linear\n", " )\n", " return pd.Series(resized_pattern).vbt.plot()" ] }, { "cell_type": "code", "execution_count": null, "id": "2e4d8724-6fc6-436e-b9aa-abdf9d97b12b", "metadata": {}, "outputs": [], "source": [ "plot_linear(7).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "f377c765-e433-4059-a757-50ba4da8a9c0", "metadata": {}, "outputs": [], "source": [ "resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, 7, vbt.enums.InterpMode.Linear\n", ")\n", "ratio = (len(pattern) - 1) / (len(resized_pattern) - 1)\n", "new_points = np.arange(len(resized_pattern)) * ratio\n", "fig = pd.Series(pattern).vbt.plot()\n", "pd.Series(resized_pattern, index=new_points).vbt.scatterplot(fig=fig).show_svg()" ] }, { "cell_type": "markdown", "id": "f0090d25-94e2-4be3-a4ae-e86f6f766228", "metadata": {}, "source": [ "#### Nearest" ] }, { "cell_type": "code", "execution_count": null, "id": "7727b0c3-2d09-43c1-be29-f4c0b40a6e36", "metadata": {}, "outputs": [], "source": [ "resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, 10, vbt.enums.InterpMode.Nearest\n", ")\n", "resized_pattern" ] }, { "cell_type": "code", "execution_count": null, "id": "13433f4a-b921-4be1-9f5f-8d3cc8b07eb4", "metadata": {}, "outputs": [], "source": [ "def plot_nearest(n):\n", " resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, n, vbt.enums.InterpMode.Nearest\n", " )\n", " return pd.Series(resized_pattern).vbt.plot()" ] }, { "cell_type": "code", "execution_count": null, "id": "c6a581f9-446f-4424-b6a1-535aa9bd6248", "metadata": {}, "outputs": [], "source": [ "plot_nearest(7).show_svg()" ] }, { "cell_type": "markdown", "id": "07bcf923-36ac-41c3-b660-a70d78917584", "metadata": {}, "source": [ "#### Discrete" ] }, { "cell_type": "code", "execution_count": null, "id": "40e606f5-9bf1-41ef-acf2-86e595e73407", "metadata": {}, "outputs": [], "source": [ "resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, 10, vbt.enums.InterpMode.Discrete\n", ")\n", "resized_pattern" ] }, { "cell_type": "code", "execution_count": null, "id": "be23bbd3-9ab7-458b-bfcd-a8b0d8625420", "metadata": {}, "outputs": [], "source": [ "def plot_discrete(n):\n", " resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, n, vbt.enums.InterpMode.Discrete\n", " )\n", " return pd.Series(resized_pattern).vbt.plot(\n", " trace_kwargs=dict(\n", " line=dict(dash=\"dot\"), \n", " connectgaps=True\n", " )\n", " )" ] }, { "cell_type": "code", "execution_count": null, "id": "1091a1ec-3be9-49a3-a600-d47a45536131", "metadata": {}, "outputs": [], "source": [ "plot_discrete(7).show_svg()" ] }, { "cell_type": "markdown", "id": "8d730164-6099-42cf-8bd0-f4b8b531a221", "metadata": {}, "source": [ "#### Mixed" ] }, { "cell_type": "code", "execution_count": null, "id": "d9f7a8c5-0361-43b3-bcdd-d68173155404", "metadata": {}, "outputs": [], "source": [ "resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, 10, vbt.enums.InterpMode.Mixed\n", ")\n", "resized_pattern" ] }, { "cell_type": "code", "execution_count": null, "id": "0c7bc0c0-8f09-4191-a4e4-644fd067b8e1", "metadata": {}, "outputs": [], "source": [ "def plot_mixed(n):\n", " lin_resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, n, vbt.enums.InterpMode.Linear\n", " )\n", " mix_resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, n, vbt.enums.InterpMode.Mixed\n", " )\n", " fig = pd.Series(lin_resized_pattern, name=\"Linear\").vbt.plot()\n", " return pd.Series(mix_resized_pattern, name=\"Mixed\").vbt.plot(fig=fig)" ] }, { "cell_type": "code", "execution_count": null, "id": "7f44cc40-77ee-4e1d-9c4c-acb926793cf0", "metadata": {}, "outputs": [], "source": [ "plot_mixed(7).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "1a3ce6d1-8a17-4320-9421-91b6baf63672", "metadata": {}, "outputs": [], "source": [ "resized_pattern = vbt.nb.interp_resize_1d_nb(\n", " pattern, len(price_window), vbt.enums.InterpMode.Mixed\n", ")\n", "resized_pattern.shape" ] }, { "cell_type": "markdown", "id": "dd584ad8-1021-440f-8560-05e5bb00773f", "metadata": {}, "source": [ "### Rescaling" ] }, { "cell_type": "code", "execution_count": null, "id": "71c86abd-dfa5-474c-bad9-d8027dc6f7f1", "metadata": {}, "outputs": [], "source": [ "pattern_scale = (resized_pattern.min(), resized_pattern.max())\n", "price_window_scale = (price_window.min(), price_window.max())\n", "rescaled_pattern = vbt.utils.array_.rescale_nb(\n", " resized_pattern, pattern_scale, price_window_scale\n", ")\n", "rescaled_pattern = pd.Series(rescaled_pattern, index=price_window.index)" ] }, { "cell_type": "code", "execution_count": null, "id": "118dc7e7-a701-4ca9-986a-f3d0ba840a0d", "metadata": {}, "outputs": [], "source": [ "fig = price_window.vbt.plot()\n", "rescaled_pattern.vbt.plot(\n", " trace_kwargs=dict(\n", " fill=\"tonexty\", \n", " fillcolor=\"rgba(255, 100, 0, 0.25)\"\n", " ), \n", " fig=fig\n", ").show_svg()" ] }, { "cell_type": "markdown", "id": "3f2b7762-2194-48c3-9c01-6b545edfa00f", "metadata": {}, "source": [ "#### Rebasing" ] }, { "cell_type": "code", "execution_count": null, "id": "3cd899eb-3a74-4a7d-ac80-f84f70d2c582", "metadata": {}, "outputs": [], "source": [ "pct_pattern = np.array([1, 1.3, 1.6, 1.3, 1.6, 1.3])\n", "resized_pct_pattern = vbt.nb.interp_resize_1d_nb(\n", " pct_pattern, len(price_window), vbt.enums.InterpMode.Mixed\n", ")\n", "rebased_pattern = resized_pct_pattern / resized_pct_pattern[0]\n", "rebased_pattern *= price_window.values[0]\n", "rebased_pattern = pd.Series(rebased_pattern, index=price_window.index)\n", "fig = price_window.vbt.plot()\n", "rebased_pattern.vbt.plot(\n", " trace_kwargs=dict(\n", " fill=\"tonexty\", \n", " fillcolor=\"rgba(255, 100, 0, 0.25)\"\n", " ), \n", " fig=fig\n", ").show_svg()" ] }, { "cell_type": "markdown", "id": "04a1cec7-cbd2-4653-8908-04e8439f3079", "metadata": {}, "source": [ "### Similarity" ] }, { "cell_type": "code", "execution_count": null, "id": "5a91fb91-2c80-49ec-a3ba-fd548952b2b2", "metadata": {}, "outputs": [], "source": [ "abs_distances = np.abs(rescaled_pattern - price_window.values)\n", "mae = abs_distances.sum()\n", "max_abs_distances = np.column_stack((\n", " (price_window.max() - rescaled_pattern), \n", " (rescaled_pattern - price_window.min())\n", ")).max(axis=1)\n", "max_mae = max_abs_distances.sum()\n", "similarity = 1 - mae / max_mae\n", "similarity" ] }, { "cell_type": "code", "execution_count": null, "id": "71c95949-c983-46b5-9393-e8d842d9652b", "metadata": {}, "outputs": [], "source": [ "quad_distances = (rescaled_pattern - price_window.values) ** 2\n", "rmse = np.sqrt(quad_distances.sum())\n", "max_quad_distances = np.column_stack((\n", " (price_window.max() - rescaled_pattern), \n", " (rescaled_pattern - price_window.min())\n", ")).max(axis=1) ** 2\n", "max_rmse = np.sqrt(max_quad_distances.sum())\n", "similarity = 1 - rmse / max_rmse\n", "similarity" ] }, { "cell_type": "code", "execution_count": null, "id": "1a6017cf-5a86-4b3d-9aa9-18d5729817cf", "metadata": {}, "outputs": [], "source": [ "quad_distances = (rescaled_pattern - price_window.values) ** 2\n", "mse = quad_distances.sum()\n", "max_quad_distances = np.column_stack((\n", " (price_window.max() - rescaled_pattern), \n", " (rescaled_pattern - price_window.min())\n", ")).max(axis=1) ** 2\n", "max_mse = max_quad_distances.sum()\n", "similarity = 1 - mse / max_mse\n", "similarity" ] }, { "cell_type": "code", "execution_count": null, "id": "d8eb54f6-9562-4a95-b793-c9f661835d01", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(price_window.values, pattern)" ] }, { "cell_type": "code", "execution_count": null, "id": "8ff3ef28-c13d-4eb2-804f-bb4a008c60a0", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pct_pattern, \n", " rescale_mode=vbt.enums.RescaleMode.Rebase\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "bbba899c-eb0a-4c10-ba0a-da3d92db43ac", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pct_pattern, \n", " interp_mode=vbt.enums.InterpMode.Nearest,\n", " rescale_mode=vbt.enums.RescaleMode.Rebase,\n", " distance_measure=vbt.enums.DistanceMeasure.RMSE\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "58aca67c-c274-4d11-a6b8-c8d68d45dc44", "metadata": {}, "outputs": [], "source": [ "price_window.vbt.plot_pattern(\n", " pct_pattern, \n", " interp_mode=\"nearest\",\n", " rescale_mode=\"rebase\",\n", " fill_distance=True\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "9dc007d9-1cdf-4783-9217-4f032fee6284", "metadata": {}, "outputs": [], "source": [ "adj_pct_pattern = np.array([1, 1.3, 1.6, 1.45, 1.6, 1.3])\n", "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " adj_pct_pattern, \n", " interp_mode=vbt.enums.InterpMode.Nearest,\n", " rescale_mode=vbt.enums.RescaleMode.Rebase,\n", " distance_measure=vbt.enums.DistanceMeasure.RMSE\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "21f3b1f9-d97e-4c34-8f36-a316a8a26221", "metadata": {}, "outputs": [], "source": [ "price_window.vbt.plot_pattern(\n", " adj_pct_pattern, \n", " interp_mode=\"discrete\",\n", " rescale_mode=\"rebase\",\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "deb354ad-8971-4d44-bbc5-fabccb5afc2e", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " adj_pct_pattern, \n", " interp_mode=vbt.enums.InterpMode.Discrete,\n", " rescale_mode=vbt.enums.RescaleMode.Rebase,\n", " distance_measure=vbt.enums.DistanceMeasure.RMSE\n", ")" ] }, { "cell_type": "markdown", "id": "71532171-5624-4c6b-9dd0-1853590b31f2", "metadata": {}, "source": [ "#### Relative" ] }, { "cell_type": "code", "execution_count": null, "id": "f72cd3c8-a561-485e-9ab6-30edefc53143", "metadata": {}, "outputs": [], "source": [ "abs_pct_distances = abs_distances / rescaled_pattern\n", "pct_mae = abs_pct_distances.sum()\n", "max_abs_pct_distances = max_abs_distances / rescaled_pattern\n", "max_pct_mae = max_abs_pct_distances.sum()\n", "similarity = 1 - pct_mae / max_pct_mae\n", "similarity" ] }, { "cell_type": "code", "execution_count": null, "id": "d4b8a531-000f-4837-a069-388897e709e1", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pct_pattern, \n", " error_type=vbt.enums.ErrorType.Relative\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "7784e836-786a-4e92-a605-431beb635e12", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " np.array([10, 30, 100]),\n", " np.array([1, 2, 3]),\n", " error_type=vbt.enums.ErrorType.Absolute\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "bfcec566-fb2e-42b6-b8f1-03dc347f2986", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " np.array([10, 30, 100]),\n", " np.array([1, 2, 3]),\n", " error_type=vbt.enums.ErrorType.Relative\n", ")" ] }, { "cell_type": "markdown", "id": "e2a99c01-cafb-443e-9851-a54cd04114c7", "metadata": {}, "source": [ "#### Inverse" ] }, { "cell_type": "code", "execution_count": null, "id": "fc894117-9148-4e6f-a812-c01f15aa8d66", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(price_window.values, pattern, invert=True)" ] }, { "cell_type": "code", "execution_count": null, "id": "f932cc4d-885f-46b0-b306-e05eb3329d6b", "metadata": {}, "outputs": [], "source": [ "price_window.vbt.plot_pattern(pattern, invert=True).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "a5faa78d-c7c7-47f3-8847-bf19c4b4ee04", "metadata": {}, "outputs": [], "source": [ "pattern.max() + pattern.min() - pattern" ] }, { "cell_type": "markdown", "id": "5e8bd3c8-4112-4c57-9b37-05b79a0f483c", "metadata": {}, "source": [ "#### Max error" ] }, { "cell_type": "code", "execution_count": null, "id": "2f2e0182-3e5e-4809-bde4-ff4aeaf33ce2", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pattern,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "cbd19ab7-16d6-4c94-9ca1-bbba7ea8f88d", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pattern, \n", " max_error=np.array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5]),\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "bf4b4ec8-9665-4400-9fa5-bebf204eeb4a", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pattern, \n", " max_error=np.array([0.5]),\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "e562481d-6e22-4d6f-99af-4a6e763fdbcd", "metadata": {}, "outputs": [], "source": [ "price_window.vbt.plot_pattern(\n", " pattern, \n", " max_error=0.5\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "2b697b1e-6806-4813-84c0-59fc58b7c1ab", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pattern, \n", " max_error=np.array([0.5]),\n", " max_error_strict=True\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "9a20ef9a-11fe-418b-a6c5-1334826176bd", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " adj_pct_pattern, \n", " rescale_mode=vbt.enums.RescaleMode.Rebase,\n", " max_error=np.array([0.2, 0.1, 0.05, 0.1, 0.05, 0.1]),\n", " max_error_strict=True\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "ab8bbd05-b4f0-421f-8180-05ad7c84087e", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pattern, \n", " max_error=np.array([0.1]),\n", " error_type=vbt.enums.ErrorType.Relative\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "b6ff62e3-ccee-40bb-9e03-ab1e78f12547", "metadata": {}, "outputs": [], "source": [ "price_window.vbt.plot_pattern(\n", " pattern, \n", " max_error=0.1,\n", " error_type=\"relative\"\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "a741780d-857d-4111-9731-00ac63e8bdcb", "metadata": {}, "outputs": [], "source": [ "price_window.vbt.plot_pattern(\n", " adj_pct_pattern, \n", " rescale_mode=\"rebase\",\n", " max_error=np.array([0.2, 0.1, 0.05, 0.1, 0.05, 0.1])\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "71b9ca1e-8074-45f2-b62a-9e8fddb560a5", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " adj_pct_pattern, \n", " rescale_mode=vbt.enums.RescaleMode.Rebase,\n", " max_error=np.array([0.2, 0.1, 0.05, 0.1, 0.05, 0.1]) + 0.05,\n", " max_error_strict=True\n", ")" ] }, { "cell_type": "markdown", "id": "bacece86-cc55-4499-959b-49eb7c99a8c8", "metadata": {}, "source": [ "##### Interpolation" ] }, { "cell_type": "code", "execution_count": null, "id": "f92c333c-fe6e-41bc-9f17-fcd9d8846b24", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " adj_pct_pattern, \n", " rescale_mode=vbt.enums.RescaleMode.Rebase,\n", " max_error=np.array([np.nan, np.nan, 0.1, np.nan, 0.1, np.nan]),\n", " max_error_interp_mode=vbt.enums.InterpMode.Discrete,\n", " max_error_strict=True\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "0b4ea56d-a9fd-4b5e-b8be-4212ae0a2815", "metadata": {}, "outputs": [], "source": [ "price_window.vbt.plot_pattern(\n", " adj_pct_pattern, \n", " rescale_mode=\"rebase\",\n", " max_error=np.array([np.nan, np.nan, 0.1, np.nan, 0.1, np.nan]),\n", " max_error_interp_mode=\"discrete\"\n", ").show_svg()" ] }, { "cell_type": "markdown", "id": "f42d2d89-09a2-469c-9490-84267a973202", "metadata": {}, "source": [ "##### Max distance" ] }, { "cell_type": "code", "execution_count": null, "id": "dc55ea4c-35b3-4fef-952a-ece601444a72", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(price_window.values, pattern)" ] }, { "cell_type": "code", "execution_count": null, "id": "29587bc3-998e-4096-be6b-e4e91902e4ae", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(\n", " price_window.values, \n", " pattern, \n", " max_error=np.array([0.5]),\n", " max_error_as_maxdist=True\n", ")" ] }, { "cell_type": "markdown", "id": "481524c4-d6c6-4f2e-a862-f60f65149a84", "metadata": {}, "source": [ "#### Further filters" ] }, { "cell_type": "code", "execution_count": null, "id": "112660d1-e7be-4f51-9db4-93b79a22fca9", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(price_window.values, pattern, max_pct_change=0.3)" ] }, { "cell_type": "code", "execution_count": null, "id": "a3fe67b2-0532-45d3-a757-e03a8f05f7f5", "metadata": {}, "outputs": [], "source": [ "vbt.nb.pattern_similarity_nb(price_window.values, pattern, min_similarity=0.9)" ] }, { "cell_type": "markdown", "id": "df50b2a9-7bf7-47c8-8292-91043252f9cc", "metadata": {}, "source": [ "### Rolling similarity" ] }, { "cell_type": "code", "execution_count": null, "id": "97dc4e9d-9285-4909-9499-6792d44379d9", "metadata": {}, "outputs": [], "source": [ "price = data.hlc3\n", "\n", "similarity = price.vbt.rolling_pattern_similarity(\n", " pattern, \n", " window=30,\n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\"\n", ")\n", "similarity.describe()" ] }, { "cell_type": "code", "execution_count": null, "id": "27d7ae88-d60d-4be7-be44-d148d3dcef1b", "metadata": {}, "outputs": [], "source": [ "end_row = similarity.argmax() + 1\n", "start_row = end_row - 30\n", "fig = data.iloc[start_row:end_row].plot(plot_volume=False)\n", "price.iloc[start_row:end_row].vbt.plot_pattern(\n", " pattern, \n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\",\n", " plot_obj=False, \n", " fig=fig\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "0a018943-adff-4249-a2b4-d6a7cb34e62f", "metadata": {}, "outputs": [], "source": [ "end_row = similarity.argmin() + 1\n", "start_row = end_row - 30\n", "fig = data.iloc[start_row:end_row].plot(plot_volume=False)\n", "price.iloc[start_row:end_row].vbt.plot_pattern(\n", " pattern, \n", " invert=True,\n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\",\n", " plot_obj=False, \n", " fig=fig\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "c98cfea9-5b10-4c9a-a0de-c526ba4cb7ab", "metadata": {}, "outputs": [], "source": [ "inv_similarity = price.vbt.rolling_pattern_similarity(\n", " pattern, \n", " window=30,\n", " invert=True,\n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\"\n", ")\n", "inv_similarity.describe()" ] }, { "cell_type": "code", "execution_count": null, "id": "1c76c75f-1eb8-44dd-a633-ec4574c02ce7", "metadata": {}, "outputs": [], "source": [ "end_row = inv_similarity.argmax() + 1\n", "start_row = end_row - 30\n", "fig = data.iloc[start_row:end_row].plot(plot_volume=False)\n", "price.iloc[start_row:end_row].vbt.plot_pattern(\n", " pattern, \n", " invert=True,\n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\",\n", " plot_obj=False, \n", " fig=fig\n", ").show_svg()" ] }, { "cell_type": "markdown", "id": "b0f936be-2cb1-483a-8388-36bcd2292c95", "metadata": {}, "source": [ "#### Indicator" ] }, { "cell_type": "code", "execution_count": null, "id": "2c66d09c-3d29-4656-bb90-6d3e60010e85", "metadata": {}, "outputs": [], "source": [ "patsim = vbt.PATSIM.run(\n", " price, \n", " vbt.Default(pattern),\n", " error_type=vbt.Default(\"relative\"),\n", " max_error=vbt.Default(0.05),\n", " max_error_interp_mode=vbt.Default(\"discrete\"),\n", " window=[30, 45, 60, 75, 90]\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "789f1c55-f448-4d74-9619-2e45c5d25ae7", "metadata": {}, "outputs": [], "source": [ "patsim.wrapper.columns" ] }, { "cell_type": "code", "execution_count": null, "id": "e4f9c2a7-f251-49ea-90e2-1b8d3be2fdc2", "metadata": {}, "outputs": [], "source": [ "patsim.plot(column=60).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "d2341e8a-539c-4426-ba18-abda070b0c0f", "metadata": {}, "outputs": [], "source": [ "patsim.overlay_with_heatmap(column=60).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "18d865d5-3942-47fd-b01c-0837d2bad35e", "metadata": {}, "outputs": [], "source": [ "exits = patsim.similarity >= 0.8\n", "exits.sum()" ] }, { "cell_type": "code", "execution_count": null, "id": "08cc861a-5d5a-4b43-80ce-00b18e7fd3e3", "metadata": {}, "outputs": [], "source": [ "patsim = vbt.PATSIM.run(\n", " price, \n", " vbt.Default(pattern),\n", " error_type=vbt.Default(\"relative\"),\n", " max_error=vbt.Default(0.05),\n", " max_error_interp_mode=vbt.Default(\"discrete\"),\n", " window=[30, 45, 60, 75, 90],\n", " invert=[False, True],\n", " min_similarity=[0.7, 0.8],\n", " param_product=True\n", ")\n", "exits = ~patsim.similarity.isnull()\n", "exits.sum()" ] }, { "cell_type": "code", "execution_count": null, "id": "5911f6c0-29dc-466e-be6d-367e69d4c507", "metadata": {}, "outputs": [], "source": [ "groupby = [\n", " name for name in patsim.wrapper.columns.names \n", " if name != \"patsim_window\"\n", "]\n", "max_sim = patsim.similarity.groupby(groupby, axis=1).max()\n", "entries = ~max_sim.xs(True, level=\"patsim_invert\", axis=1).isnull()\n", "exits = ~max_sim.xs(False, level=\"patsim_invert\", axis=1).isnull()" ] }, { "cell_type": "code", "execution_count": null, "id": "d4155041-905e-42d1-87d4-bcc09e06e266", "metadata": {}, "outputs": [], "source": [ "fig = data.plot(ohlc_trace_kwargs=dict(opacity=0.5))\n", "entries[0.8].vbt.signals.plot_as_entries(price, fig=fig)\n", "exits[0.8].vbt.signals.plot_as_exits(price, fig=fig).show_svg()" ] }, { "cell_type": "markdown", "id": "f4cab670-88b0-4c00-9170-ca310b7624ab", "metadata": {}, "source": [ "### Search" ] }, { "cell_type": "code", "execution_count": null, "id": "3c039275-8a26-435f-ac58-ba3f418931cd", "metadata": {}, "outputs": [], "source": [ "pattern_range_records = vbt.nb.find_pattern_1d_nb(\n", " price.values,\n", " pattern,\n", " window=30,\n", " max_window=90,\n", " error_type=vbt.enums.ErrorType.Relative,\n", " max_error=np.array([0.05]),\n", " max_error_interp_mode=vbt.enums.InterpMode.Discrete,\n", " min_similarity=0.85\n", ")\n", "pattern_range_records" ] }, { "cell_type": "code", "execution_count": null, "id": "9dbed8af-829e-4ee3-ab21-416ce30b5356", "metadata": {}, "outputs": [], "source": [ "start_row = pattern_range_records[1][\"start_idx\"]\n", "end_row = pattern_range_records[1][\"end_idx\"]\n", "fig = data.iloc[start_row:end_row + 30].plot(plot_volume=False)\n", "price.iloc[start_row:end_row].vbt.plot_pattern(\n", " pattern, \n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\",\n", " plot_obj=False, \n", " fig=fig\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "d9b75568-2605-40cf-a303-203d0d4a99d0", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = vbt.PatternRanges.from_pattern_search(\n", " price,\n", " pattern,\n", " window=30,\n", " max_window=120,\n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\",\n", " min_similarity=0.85\n", ")\n", "pattern_ranges" ] }, { "cell_type": "code", "execution_count": null, "id": "4173fd82-22f4-4f7f-afac-64d17836a608", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " pattern,\n", " window=30,\n", " max_window=90,\n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\",\n", " min_similarity=0.85\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "f58a06d1-9df6-4e26-9541-fa5c45e52368", "metadata": {}, "outputs": [], "source": [ "print(pattern_ranges.records_readable)" ] }, { "cell_type": "code", "execution_count": null, "id": "d83797be-ea9a-4f66-b27b-13a70e121735", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.wrapper.columns" ] }, { "cell_type": "code", "execution_count": null, "id": "b2d620cb-8deb-4fda-a62c-ccf8e0b126d1", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.search_configs" ] }, { "cell_type": "code", "execution_count": null, "id": "db1df1d9-69ae-4a84-8a45-57df9f16d9bb", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.plot().show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "1e006d13-e92d-4e72-999d-442ec8cd867a", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.loc[\"2021-09-01\":\"2022-01-01\"].plot().show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "31895f9e-9dab-44b4-b810-02549c01a3b6", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.stats()" ] }, { "cell_type": "markdown", "id": "099ecd8c-d9dd-40fc-b766-53c619240991", "metadata": {}, "source": [ "#### Overlapping" ] }, { "cell_type": "code", "execution_count": null, "id": "5b33eb7c-2e4c-4a66-8ebf-6ff6fe82639c", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " pattern,\n", " window=30,\n", " max_window=120,\n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\",\n", " min_similarity=0.85,\n", " overlap_mode=\"allow\"\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "0c924f37-e0c3-4588-8515-3684ef4eb46c", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "37de96f6-27f2-4538-88a5-2758c5442ea4", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.overlap_coverage" ] }, { "cell_type": "code", "execution_count": null, "id": "b9a5bc35-4f8d-4add-af11-c2ac583fe70a", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.plot(plot_zones=False, plot_patterns=False).show_svg()" ] }, { "cell_type": "markdown", "id": "532a3db0-a81e-46f5-945c-37a0774a17a7", "metadata": {}, "source": [ "#### Random selection" ] }, { "cell_type": "code", "execution_count": null, "id": "8c163259-3d64-4d06-a824-834d21043434", "metadata": {}, "outputs": [], "source": [ "def run_prob_search(row_select_prob, window_select_prob):\n", " return price.vbt.find_pattern(\n", " pattern,\n", " window=30,\n", " max_window=120,\n", " row_select_prob=row_select_prob,\n", " window_select_prob=window_select_prob,\n", " error_type=\"relative\",\n", " max_error=0.05,\n", " max_error_interp_mode=\"discrete\",\n", " min_similarity=0.8,\n", " )" ] }, { "cell_type": "code", "execution_count": null, "id": "5f08fb98-3b7c-41b2-a8b9-ba9ba7f4d475", "metadata": {}, "outputs": [], "source": [ "%timeit run_prob_search(1.0, 1.0)" ] }, { "cell_type": "code", "execution_count": null, "id": "3cefffe3-5d70-4a3d-822a-d39ea0f3b30a", "metadata": {}, "outputs": [], "source": [ "%timeit run_prob_search(0.5, 0.25)" ] }, { "cell_type": "code", "execution_count": null, "id": "d3a04c29-284e-4840-a77d-f23638962cd9", "metadata": {}, "outputs": [], "source": [ "run_prob_search(1.0, 1.0).count()" ] }, { "cell_type": "code", "execution_count": null, "id": "d1ff96a9-7c06-4f27-9e88-90e8902aae8a", "metadata": {}, "outputs": [], "source": [ "pd.Series([\n", " run_prob_search(0.5, 0.25).count() \n", " for i in range(100)\n", "]).vbt.plot().show_svg()" ] }, { "cell_type": "markdown", "id": "292d8003-d997-4826-b2cf-827786c66d55", "metadata": {}, "source": [ "#### Params" ] }, { "cell_type": "code", "execution_count": null, "id": "9f47a2b9-3d72-4b4a-a544-17bb08600836", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " vbt.Param([\n", " [1, 2, 1],\n", " [2, 1, 2],\n", " [1, 2, 3],\n", " [3, 2, 1]\n", " ]),\n", " window=30,\n", " max_window=120,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "e2dffbc9-e64b-4629-83ce-af6bc96c701b", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "294ee0c1-74f1-4d08-9627-9d7f78bb7c1d", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " vbt.Param([\n", " [1, 2, 1],\n", " [2, 1, 2],\n", " [1, 2, 3],\n", " [3, 2, 1]\n", " ], keys=[\"v-top\", \"v-bottom\", \"rising\", \"falling\"]),\n", " window=30,\n", " max_window=120,\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "596fe13e-d557-4115-871f-393d993e1922", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.plot(column=\"falling\").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "e484ac50-c92c-4287-bd7a-f7ecdd3ca523", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " vbt.Param([\n", " [1, 2, 1],\n", " [2, 1, 2],\n", " [1, 2, 3],\n", " [3, 2, 1]\n", " ], keys=[\"v-top\", \"v-bottom\", \"rising\", \"falling\"]),\n", " window=30,\n", " max_window=120,\n", " min_similarity=vbt.Param([0.8, 0.85])\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "bcf16c45-3021-49d6-9033-82ddd96a0f30", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.plot(column=(\"v-bottom\", 0.8)).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "7da6b0a3-899b-41a7-a514-68ccedea422f", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " vbt.Param([\n", " [1, 2, 1],\n", " [2, 1, 2],\n", " [1, 2, 3],\n", " [3, 2, 1]\n", " ], keys=[\"v-top\", \"v-bottom\", \"rising\", \"falling\"], level=0),\n", " window=vbt.Param([30, 30, 7, 7], level=0),\n", " max_window=vbt.Param([120, 120, 30, 30], level=0),\n", " min_similarity=vbt.Param([0.8, 0.85], level=1)\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "markdown", "id": "c289b606-0c93-48d2-9eb4-4ee571bc4636", "metadata": {}, "source": [ "#### Configs" ] }, { "cell_type": "code", "execution_count": null, "id": "0c3bbcfc-6336-4241-a259-4cbf45a37d72", "metadata": {}, "outputs": [], "source": [ "mult_data = vbt.BinanceData.pull(\n", " [\"BTCUSDT\", \"ETHUSDT\"], \n", " start=\"2020-06-01 UTC\", \n", " end=\"2022-06-01 UTC\"\n", ")\n", "mult_price = mult_data.hlc3" ] }, { "cell_type": "code", "execution_count": null, "id": "0c15e655-b3be-4223-992d-a4b27d82a5eb", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = mult_price.vbt.find_pattern(\n", " search_configs=[\n", " vbt.PSC(pattern=[1, 2, 3, 2, 3, 2], window=30),\n", " [\n", " vbt.PSC(pattern=mult_price.iloc[-30:, 0]),\n", " vbt.PSC(pattern=mult_price.iloc[-30:, 1]),\n", " ]\n", " ],\n", " min_similarity=0.8\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "3c19e67e-70ab-4a0e-ad63-46e24b9121ed", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = mult_price.vbt.find_pattern(\n", " search_configs=[\n", " vbt.PSC(pattern=[1, 2, 3, 2, 3, 2], window=30, name=\"double_top\"),\n", " [\n", " vbt.PSC(pattern=mult_price.iloc[-30:, 0], name=\"last\"),\n", " vbt.PSC(pattern=mult_price.iloc[-30:, 1], name=\"last\"),\n", " ]\n", " ],\n", " min_similarity=0.8\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "97bdb94f-ea9b-4321-b858-3b49e29dd04b", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = mult_price.vbt.find_pattern(\n", " search_configs=[\n", " vbt.PSC(pattern=[1, 2, 3, 2, 3, 2], window=30, name=\"double_top\"),\n", " [\n", " vbt.PSC(pattern=mult_price.iloc[-30:, 0], name=\"last\"),\n", " vbt.PSC(pattern=mult_price.iloc[-30:, 1], name=\"last\"),\n", " ]\n", " ],\n", " rescale_mode=vbt.Param([\"minmax\", \"rebase\"]),\n", " min_similarity=0.8,\n", " open=mult_data.open,\n", " high=mult_data.high,\n", " low=mult_data.low,\n", " close=mult_data.close,\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "c5f0ee35-b0be-48f8-9087-1b81cc3867ce", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.plot(column=(\"rebase\", \"last\", \"ETHUSDT\")).show_svg()" ] }, { "cell_type": "markdown", "id": "c75c253d-e60f-4cd5-8cab-6a610f82bc9c", "metadata": {}, "source": [ "#### Mask" ] }, { "cell_type": "code", "execution_count": null, "id": "3fbd7240-7dee-4ee4-b371-445abe564fd8", "metadata": {}, "outputs": [], "source": [ "mask = pattern_ranges.last_pd_mask\n", "mask.sum()" ] }, { "cell_type": "markdown", "id": "9451fb73-03e4-4287-acce-df905eec8fa4", "metadata": {}, "source": [ "#### Indicator" ] }, { "cell_type": "code", "execution_count": null, "id": "add9ccd5-966a-4262-bb18-ace8abbf9cba", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " pattern,\n", " window=30,\n", " max_window=120,\n", " row_select_prob=0.5,\n", " window_select_prob=0.5,\n", " overlap_mode=\"allow\",\n", " seed=42\n", ")\n", "pr_mask = pattern_ranges.map_field(\n", " \"similarity\", \n", " idx_arr=pattern_ranges.last_idx.values\n", ").to_pd()\n", "pr_mask[~pr_mask.isnull()]" ] }, { "cell_type": "code", "execution_count": null, "id": "86147e26-3814-4f0c-915f-cff77c5d4c28", "metadata": {}, "outputs": [], "source": [ "patsim = vbt.PATSIM.run(\n", " price,\n", " vbt.Default(pattern),\n", " window=vbt.Default(30),\n", " max_window=vbt.Default(120),\n", " row_select_prob=vbt.Default(0.5),\n", " window_select_prob=vbt.Default(0.5),\n", " min_similarity=vbt.Default(0.85),\n", " seed=42\n", ")\n", "ind_mask = patsim.similarity\n", "ind_mask[~ind_mask.isnull()]" ] }, { "cell_type": "markdown", "id": "f89ddd9d-d8a4-4bd8-800e-3dd2e962c229", "metadata": {}, "source": [ "### Combination" ] }, { "cell_type": "code", "execution_count": null, "id": "27387a58-44cc-4885-abfc-bb93e40931e0", "metadata": {}, "outputs": [], "source": [ "price_highs = vbt.PATSIM.run(\n", " data.high, \n", " pattern=np.array([1, 3, 2, 4]), \n", " window=40,\n", " max_window=50\n", ")\n", "macd = data.run(\"talib_macd\").macd\n", "macd_lows = vbt.PATSIM.run(\n", " macd, \n", " pattern=np.array([4, 2, 3, 1]), \n", " window=40,\n", " max_window=50\n", ")\n", "\n", "fig = vbt.make_subplots(\n", " rows=3, cols=1, shared_xaxes=True, vertical_spacing=0.02\n", ")\n", "fig.update_layout(height=500)\n", "data.high.rename(\"Price\").vbt.plot(\n", " add_trace_kwargs=dict(row=1, col=1), fig=fig\n", ")\n", "macd.rename(\"MACD\").vbt.plot(\n", " add_trace_kwargs=dict(row=2, col=1), fig=fig\n", ")\n", "price_highs.similarity.rename(\"Price Sim\").vbt.plot(\n", " add_trace_kwargs=dict(row=3, col=1), fig=fig\n", ")\n", "macd_lows.similarity.rename(\"MACD Sim\").vbt.plot(\n", " add_trace_kwargs=dict(row=3, col=1), fig=fig\n", ")\n", "fig.show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "4aa7cb3d-4000-443c-830c-2f5034a46c2d", "metadata": {}, "outputs": [], "source": [ "cond1 = (price_highs.similarity >= 0.8).vbt.rolling_any(10)\n", "cond2 = (macd_lows.similarity >= 0.8).vbt.rolling_any(10)\n", "exits = cond1 & cond2\n", "fig = data.plot(ohlc_trace_kwargs=dict(opacity=0.5))\n", "exits.vbt.signals.plot_as_exits(data.close, fig=fig).show_svg()" ] }, { "cell_type": "markdown", "id": "ea6d38dd-f8a7-4cfd-a0cd-0372ba13781f", "metadata": {}, "source": [ "## Projections" ] }, { "cell_type": "code", "execution_count": null, "id": "2454a1d5-d966-4511-a0d6-942eb479414b", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " [1, 1.2], \n", " window=7, \n", " rescale_mode=\"rebase\", \n", " max_error=0.01,\n", " max_error_interp_mode=\"discrete\",\n", " max_error_strict=True\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "markdown", "id": "5a5e28f0-13c5-429e-a2c8-a6d249b5fbf5", "metadata": {}, "source": [ "### Pattern projections" ] }, { "cell_type": "code", "execution_count": null, "id": "db8fb47e-92a1-4476-becb-6677d6bac612", "metadata": {}, "outputs": [], "source": [ "range_idxs, raw_projections = vbt.nb.map_ranges_to_projections_nb(\n", " vbt.to_2d_array(price),\n", " pattern_ranges.get_field_arr(\"col\"),\n", " pattern_ranges.get_field_arr(\"start_idx\"),\n", " pattern_ranges.get_field_arr(\"end_idx\"),\n", " pattern_ranges.get_field_arr(\"status\")\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "42bc6ef9-55b8-4331-9b4e-acd42d6fa28d", "metadata": {}, "outputs": [], "source": [ "range_idxs" ] }, { "cell_type": "code", "execution_count": null, "id": "3ef238f3-59b3-44c9-9164-8770077516ff", "metadata": {}, "outputs": [], "source": [ "raw_projections" ] }, { "cell_type": "code", "execution_count": null, "id": "cf6ec440-517b-4ec3-b5f2-88637429f270", "metadata": {}, "outputs": [], "source": [ "projections = pattern_ranges.get_projections()\n", "print(projections)" ] }, { "cell_type": "code", "execution_count": null, "id": "e2ecac89-f4b1-4d11-af3e-cceebf01770c", "metadata": {}, "outputs": [], "source": [ "pattern_ranges.duration.values" ] }, { "cell_type": "code", "execution_count": null, "id": "350fc784-81ac-4d40-9a8e-81eb4d7e3f4d", "metadata": {}, "outputs": [], "source": [ "projections = pattern_ranges.get_projections(incl_end_idx=False)\n", "print(projections)" ] }, { "cell_type": "code", "execution_count": null, "id": "3d68f485-f5db-4af2-be32-b547446aaade", "metadata": {}, "outputs": [], "source": [ "projections.iloc[-1] / projections.iloc[0] - 1" ] }, { "cell_type": "code", "execution_count": null, "id": "37ff3101-9abb-44e9-81f8-7bba26fc7890", "metadata": {}, "outputs": [], "source": [ "projections.vbt.plot().show_svg()" ] }, { "cell_type": "markdown", "id": "8107b799-c0cc-403f-9036-3fb69ce9d107", "metadata": {}, "source": [ "### Delta projections" ] }, { "cell_type": "code", "execution_count": null, "id": "5049cc27-b914-4a1d-b302-0bb1fd69ed21", "metadata": {}, "outputs": [], "source": [ "delta_ranges = pattern_ranges.with_delta(4)" ] }, { "cell_type": "code", "execution_count": null, "id": "be87a7da-4d2d-4522-bb00-68c9a5bd2d8b", "metadata": {}, "outputs": [], "source": [ "fig = pattern_ranges.loc[\"2021-01\":\"2021-03\"].plot()\n", "delta_ranges.loc[\"2021-01\":\"2021-03\"].plot(\n", " plot_ohlc=False,\n", " plot_close=False,\n", " plot_markers=False,\n", " closed_shape_kwargs=dict(fillcolor=\"DeepSkyBlue\"),\n", " fig=fig\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "eafc7432-212f-4029-9863-ce77680876a4", "metadata": {}, "outputs": [], "source": [ "projections = delta_ranges.get_projections()\n", "print(projections)" ] }, { "cell_type": "code", "execution_count": null, "id": "71564e43-47b6-41fa-a00b-d5dfbbc597c9", "metadata": {}, "outputs": [], "source": [ "np.mean(projections.iloc[-1] / projections.iloc[0] - 1)" ] }, { "cell_type": "code", "execution_count": null, "id": "458e3eb1-d963-4b63-b143-8e83a311b7e8", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = mult_price.vbt.find_pattern(\n", " [1, 1.2], \n", " window=7, \n", " max_window=30,\n", " rescale_mode=\"rebase\",\n", " max_error=0.01,\n", " max_error_interp_mode=\"discrete\",\n", " max_error_strict=True,\n", " overlap_mode=\"allow\"\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "962f00c1-d8d2-4f36-b9d0-b3f22d0e9b85", "metadata": {}, "outputs": [], "source": [ "delta_ranges = pattern_ranges.with_delta(4)" ] }, { "cell_type": "code", "execution_count": null, "id": "6342f033-5867-4c10-aa52-572cc6fa4b1c", "metadata": {}, "outputs": [], "source": [ "projections = delta_ranges.get_projections()" ] }, { "cell_type": "code", "execution_count": null, "id": "5d852b78-9631-471a-936b-e4ecde58306d", "metadata": {}, "outputs": [], "source": [ "(projections.iloc[-1] / projections.iloc[0] - 1).describe()" ] }, { "cell_type": "code", "execution_count": null, "id": "83317097-d330-42bc-9914-e1771223d87d", "metadata": {}, "outputs": [], "source": [ "projections = delta_ranges.get_projections(id_level=\"end_idx\")" ] }, { "cell_type": "code", "execution_count": null, "id": "b2826f67-9bca-4fb0-869e-a82cdfd2241d", "metadata": {}, "outputs": [], "source": [ "print(projections.columns)" ] }, { "cell_type": "code", "execution_count": null, "id": "81af5933-1c93-4d78-9fc1-caf11fbcebfa", "metadata": {}, "outputs": [], "source": [ "btc_projections = projections.xs(\"BTCUSDT\", level=\"symbol\", axis=1)\n", "total_proj_return = btc_projections.iloc[-1] / btc_projections.iloc[0] - 1\n", "total_proj_return.vbt.scatterplot(\n", " trace_kwargs=dict(\n", " marker=dict(\n", " color=total_proj_return.values,\n", " colorscale=\"Temps_r\",\n", " cmid=0\n", " )\n", " )\n", ").show_svg()" ] }, { "cell_type": "markdown", "id": "3052612d-739e-4850-98c0-c95339abab89", "metadata": {}, "source": [ "### Plotting" ] }, { "cell_type": "code", "execution_count": null, "id": "80393e11-1f0b-4677-8449-704c608fc663", "metadata": {}, "outputs": [], "source": [ "btc_projections.vbt.plot_projections(plot_bands=False).show_svg()" ] }, { "cell_type": "markdown", "id": "36245487-378f-485c-a8b5-943882c67d4a", "metadata": {}, "source": [ "#### Colorization" ] }, { "cell_type": "code", "execution_count": null, "id": "7899b684-bb9f-466b-ab32-c8a458dcaaf3", "metadata": {}, "outputs": [], "source": [ "btc_projections[\"2020-08-03\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "bbae99b6-bd79-4761-a841-2c4332b40e89", "metadata": {}, "outputs": [], "source": [ "btc_projections[\"2020-08-03\"].median()" ] }, { "cell_type": "code", "execution_count": null, "id": "3dc3ff43-6652-43e6-8846-4395f4961778", "metadata": {}, "outputs": [], "source": [ "btc_projections.vbt.plot_projections(\n", " plot_bands=False, colorize=np.std\n", ").show_svg()" ] }, { "cell_type": "markdown", "id": "cd341c89-03e5-49c0-bf5f-54e400e1006e", "metadata": {}, "source": [ "#### Bands" ] }, { "cell_type": "code", "execution_count": null, "id": "8289d408-7647-42e3-b031-4fca40126501", "metadata": {}, "outputs": [], "source": [ "projections.xs(\"ETHUSDT\", level=\"symbol\", axis=1).median(axis=1)" ] }, { "cell_type": "code", "execution_count": null, "id": "43533726-0d4a-4ff1-8b6d-dcfd1cc47e6b", "metadata": {}, "outputs": [], "source": [ "print(projections.groupby(\"symbol\", axis=1).median())" ] }, { "cell_type": "code", "execution_count": null, "id": "f4059411-7aec-4ca6-ba4e-16fec33303f3", "metadata": {}, "outputs": [], "source": [ "projections.median(axis=1)" ] }, { "cell_type": "code", "execution_count": null, "id": "57d904bb-d80a-48b9-a518-c1302b16ea51", "metadata": {}, "outputs": [], "source": [ "btc_projections.vbt.plot_projections().show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "3ac38bd4-62a9-4f47-ab1b-9387b5aef98d", "metadata": {}, "outputs": [], "source": [ "btc_projections.iloc[-1].quantile(0.8)" ] }, { "cell_type": "code", "execution_count": null, "id": "e66e93d8-8ff7-4f34-ae0d-ccadd66cebcc", "metadata": {}, "outputs": [], "source": [ "btc_projections.vbt.plot_projections(\n", " plot_lower=False,\n", " plot_middle=\"30%\", \n", " plot_upper=False, \n", " plot_aux_middle=False, \n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "f949a129-4ec8-4ea8-923f-34ab2c3a1927", "metadata": {}, "outputs": [], "source": [ "btc_projections.iloc[-1].vbt.qqplot().show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "4d0e1932-7d85-4b5f-8b07-a720b50033cb", "metadata": {}, "outputs": [], "source": [ "btc_projections.vbt.plot_projections(\n", " plot_lower=\"P=20%\",\n", " plot_middle=\"mean\", \n", " plot_upper=\"P=80%\", \n", " plot_aux_middle=False, \n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "c6759119-3477-4a13-9127-3fca78fbf827", "metadata": {}, "outputs": [], "source": [ "def finishes_at_quantile(df, q):\n", " nth_element = int(np.ceil(q * (df.shape[1] - 1)))\n", " nth_index = np.argsort(df.iloc[-1])[nth_element]\n", " return df.iloc[:, nth_index]\n", "\n", "btc_projections.vbt.plot_projections(\n", " plot_lower=partial(finishes_at_quantile, q=0.2),\n", " plot_middle=False, \n", " plot_upper=partial(finishes_at_quantile, q=0.8), \n", ").show_svg()" ] }, { "cell_type": "markdown", "id": "94e7b8cb-9143-4fce-bd98-5a7f4cf45a88", "metadata": {}, "source": [ "### Filtering" ] }, { "cell_type": "code", "execution_count": null, "id": "de11af10-ca2e-43e9-a4ac-5264b7ef0bb0", "metadata": {}, "outputs": [], "source": [ "crossed_mask = projections.expanding().max().iloc[1] >= 1.05\n", "filt_projections = projections.loc[:, crossed_mask]\n", "filt_projections.iloc[-1].describe()" ] }, { "cell_type": "code", "execution_count": null, "id": "09a8a128-dbbc-441a-b0b9-4c38728e4b66", "metadata": {}, "outputs": [], "source": [ "filt_projections.vbt.plot_projections().show_svg()" ] }, { "cell_type": "markdown", "id": "2baaec17-f214-45e1-9056-24efc36e8eb2", "metadata": {}, "source": [ "### Latest projections" ] }, { "cell_type": "code", "execution_count": null, "id": "30883240-2b3f-40bb-bfd0-3ec6a76cf638", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = price.vbt.find_pattern(\n", " pattern=data.close.iloc[-7:],\n", " rescale_mode=\"rebase\",\n", " overlap_mode=\"allow\"\n", ")\n", "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "a82ef541-7b12-4f5b-af56-39ca78ea6c69", "metadata": {}, "outputs": [], "source": [ "pattern_ranges = pattern_ranges.status_closed\n", "pattern_ranges.count()" ] }, { "cell_type": "code", "execution_count": null, "id": "284df49d-5235-4450-af49-f31475eedab2", "metadata": {}, "outputs": [], "source": [ "projections = pattern_ranges.get_projections()\n", "projections.vbt.plot_projections(plot_bands=False).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "463036d2-3b03-4aaf-ba51-17bbe30902db", "metadata": {}, "outputs": [], "source": [ "delta_ranges = pattern_ranges.with_delta(7)\n", "projections = delta_ranges.get_projections(start_value=-1)\n", "fig = data.iloc[-7:].plot(plot_volume=False)\n", "projections.vbt.plot_projections(fig=fig).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "40cd39a7-eee3-468f-953e-2e3e248a0a57", "metadata": {}, "outputs": [], "source": [ "projections.mean(axis=1)" ] }, { "cell_type": "code", "execution_count": null, "id": "ea7b7996-6040-4e22-a8a7-1b3158f3d3ae", "metadata": {}, "outputs": [], "source": [ "next_data = vbt.BinanceData.pull(\n", " \"BTCUSDT\", \n", " start=\"2022-05-31\", \n", " end=\"2022-06-08\"\n", ")\n", "next_data.close" ] }, { "cell_type": "markdown", "id": "17e50e87-4c45-4226-9c6e-d6f8c4fcc1ad", "metadata": {}, "source": [ "#### Quick plotting" ] }, { "cell_type": "code", "execution_count": null, "id": "ab44b469-25f6-4521-8597-508b0e90dcd0", "metadata": {}, "outputs": [], "source": [ "delta_ranges.plot_projections().show_svg()" ] }, { "cell_type": "markdown", "id": "0998e94d-1235-492f-8a43-7d5447c62ad0", "metadata": {}, "source": [ "### Non-uniform projections" ] }, { "cell_type": "code", "execution_count": null, "id": "d89bff85-7fb4-4199-acff-d3933e7a5bc1", "metadata": {}, "outputs": [], "source": [ "windows = np.arange(10, 31)\n", "window_tuples = combinations(windows, 2)\n", "window_tuples = filter(lambda x: abs(x[0] - x[1]) >= 5, window_tuples)\n", "fast_windows, slow_windows = zip(*window_tuples)\n", "fast_sma = data.run(\"sma\", fast_windows, short_name=\"fast_sma\")\n", "slow_sma = data.run(\"sma\", slow_windows, short_name=\"slow_sma\")\n", "entries = fast_sma.real_crossed_above(slow_sma.real)\n", "exits = fast_sma.real_crossed_below(slow_sma.real)\n", "\n", "entries.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "5b467365-1c39-4df8-82f9-e187695d66e8", "metadata": {}, "outputs": [], "source": [ "entry_ranges = entries.vbt.signals.delta_ranges(30, close=data.close)\n", "entry_ranges = entry_ranges.status_closed\n", "entry_ranges.count().sum()" ] }, { "cell_type": "code", "execution_count": null, "id": "9dbd119c-1ca9-4baf-9464-247c375da1bd", "metadata": {}, "outputs": [], "source": [ "exit_ranges = exits.vbt.signals.delta_ranges(30, close=data.close)\n", "exit_ranges = exit_ranges.status_closed\n", "exit_ranges.count().sum()" ] }, { "cell_type": "code", "execution_count": null, "id": "20a19b6e-3c65-4fba-8cbb-58fd37422420", "metadata": {}, "outputs": [], "source": [ "entry_projections = entry_ranges.get_projections()\n", "entry_projections.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "d0ed13b1-f9b0-4b8d-a1a1-1f45e9384387", "metadata": {}, "outputs": [], "source": [ "exit_projections = exit_ranges.get_projections()\n", "exit_projections.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "d390a0d6-8371-4b45-a859-7c2d75cc3e1f", "metadata": {}, "outputs": [], "source": [ "fig = entry_projections.vbt.plot_projections(\n", " plot_projections=False,\n", " lower_trace_kwargs=dict(name=\"Lower (entry)\", line_color=\"green\"),\n", " middle_trace_kwargs=dict(name=\"Middle (entry)\", line_color=\"green\"),\n", " upper_trace_kwargs=dict(name=\"Upper (entry)\", line_color=\"green\"),\n", " plot_aux_middle=False,\n", " plot_fill=False\n", ")\n", "fig = exit_projections.vbt.plot_projections(\n", " plot_projections=False,\n", " lower_trace_kwargs=dict(name=\"Lower (exit)\", line_color=\"orangered\"),\n", " middle_trace_kwargs=dict(name=\"Middle (exit)\", line_color=\"orangered\"),\n", " upper_trace_kwargs=dict(name=\"Upper (exit)\", line_color=\"orangered\"),\n", " plot_aux_middle=False,\n", " plot_fill=False,\n", " fig=fig\n", ")\n", "fig.show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "b9e3ff1d-8278-4715-9daf-c1bd779796fe", "metadata": {}, "outputs": [], "source": [ "entry_ranges = entries.vbt.signals.between_ranges(exits, close=data.close)\n", "entry_ranges = entry_ranges.status_closed\n", "entry_ranges.count().sum()" ] }, { "cell_type": "code", "execution_count": null, "id": "cd4ff156-429b-4815-a15d-2582ea0ce8c3", "metadata": {}, "outputs": [], "source": [ "exit_ranges = exits.vbt.signals.between_ranges(entries, close=data.close)\n", "exit_ranges = exit_ranges.status_closed\n", "exit_ranges.count().sum()" ] }, { "cell_type": "code", "execution_count": null, "id": "19678630-7b6c-41df-8ff5-10987936cdbe", "metadata": {}, "outputs": [], "source": [ "entry_projections = entry_ranges.get_projections()\n", "entry_projections.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "f1edfedd-8899-482d-8eae-fd452ea039b3", "metadata": {}, "outputs": [], "source": [ "exit_projections = exit_ranges.get_projections()\n", "exit_projections.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "efe053ae-3fc2-4011-b6dd-073f1898b261", "metadata": {}, "outputs": [], "source": [ "rand_cols = np.random.choice(entry_projections.shape[1], 100)\n", "entry_projections.iloc[:, rand_cols].vbt.plot_projections(plot_bands=False).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "0307a36b-6cea-41b5-97fc-9d580c6e16fc", "metadata": {}, "outputs": [], "source": [ "rand_cols = np.random.choice(exit_projections.shape[1], 100)\n", "exit_projections.iloc[:, rand_cols].vbt.plot_projections(plot_bands=False).show_svg()" ] }, { "cell_type": "markdown", "id": "efb5dbd7-92dc-4b11-9e17-53149dc69094", "metadata": {}, "source": [ "#### Shrinking" ] }, { "cell_type": "code", "execution_count": null, "id": "4e8bc5c4-6468-4d22-83ad-5eba09672b54", "metadata": {}, "outputs": [], "source": [ "entry_projections = entry_ranges.get_projections(proj_period=\"30d\")\n", "entry_projections.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "255f0a7f-b55c-4c66-bf7c-45cc0285fe84", "metadata": {}, "outputs": [], "source": [ "exit_projections = exit_ranges.get_projections(proj_period=\"30d\")\n", "exit_projections.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "31b7b35d-a419-4077-99a7-7138b0fdbfe2", "metadata": {}, "outputs": [], "source": [ "rand_cols = np.random.choice(entry_projections.shape[1], 100)\n", "entry_projections.iloc[:, rand_cols].vbt.plot_projections().show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "b6de42c1-2359-44d9-b7b4-f301dcb82877", "metadata": {}, "outputs": [], "source": [ "rand_cols = np.random.choice(exit_projections.shape[1], 100)\n", "exit_projections.iloc[:, rand_cols].vbt.plot_projections().show_svg()" ] }, { "cell_type": "markdown", "id": "bc947af3-c7fe-4c91-925b-2cb5c8062217", "metadata": {}, "source": [ "#### Stretching" ] }, { "cell_type": "code", "execution_count": null, "id": "9cd9fc97-d3be-44b8-a907-99b9db01faa4", "metadata": {}, "outputs": [], "source": [ "entry_projections = entry_ranges.get_projections(\n", " proj_period=\"30d\", extend=True\n", ")\n", "entry_projections.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "0584041b-86cc-4ce5-a127-e0cfd80e9c4a", "metadata": {}, "outputs": [], "source": [ "exit_projections = exit_ranges.get_projections(\n", " proj_period=\"30d\", extend=True\n", ")\n", "exit_projections.shape" ] }, { "cell_type": "code", "execution_count": null, "id": "307b1297-555e-4db5-a739-ca5ddf4a7157", "metadata": {}, "outputs": [], "source": [ "rand_cols = np.random.choice(entry_projections.shape[1], 100)\n", "entry_projections.iloc[:, rand_cols].vbt.plot_projections().show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "14a8234f-11e1-4841-b55e-a63483a3fce3", "metadata": {}, "outputs": [], "source": [ "rand_cols = np.random.choice(exit_projections.shape[1], 100)\n", "exit_projections.iloc[:, rand_cols].vbt.plot_projections().show_svg()" ] }, { "cell_type": "markdown", "id": "ceac936f-10c8-41c3-8b42-fcac372e8b0b", "metadata": {}, "source": [ "#### Quick plotting" ] }, { "cell_type": "code", "execution_count": null, "id": "f53ea678-3707-41af-807d-4690abde298e", "metadata": {}, "outputs": [], "source": [ "entry_ranges.wrapper.columns" ] }, { "cell_type": "code", "execution_count": null, "id": "8c128064-5e25-4949-9ab6-d01867d7523d", "metadata": {}, "outputs": [], "source": [ "entry_ranges.plot_projections(\n", " column=(25, 30),\n", " last_n=10,\n", " proj_period=\"30d\", \n", " extend=True,\n", " plot_lower=False,\n", " plot_upper=False,\n", " plot_aux_middle=False,\n", " projection_trace_kwargs=dict(opacity=0.3)\n", ").show_svg()" ] }, { "cell_type": "markdown", "id": "86fa4fc5-010e-4102-979a-f5a0f39af5c7", "metadata": {}, "source": [ "### Open projections" ] }, { "cell_type": "code", "execution_count": null, "id": "55fd0811-5970-4fe4-88d4-852cb352430e", "metadata": {}, "outputs": [], "source": [ "exit_ranges = exits.vbt.signals.between_ranges(\n", " entries, \n", " incl_open=True, \n", " close=data.close\n", ")\n", "exit_ranges.count().sum()" ] }, { "cell_type": "code", "execution_count": null, "id": "a6ee4056-46c3-48c3-a0c8-dd6c7fd96331", "metadata": {}, "outputs": [], "source": [ "exit_ranges.wrapper.columns[exit_ranges.status_open.col_arr]" ] }, { "cell_type": "code", "execution_count": null, "id": "6012e861-9761-4244-a94c-1c19726cad31", "metadata": {}, "outputs": [], "source": [ "exit_ranges.status_closed.plot_projections(\n", " column=(20, 30), plot_bands=False\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "d98c6dfb-80d6-4bab-89e6-9526397b9a39", "metadata": {}, "outputs": [], "source": [ "exit_ranges.plot_projections(\n", " column=(20, 30), plot_bands=False\n", ").show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "93a55365-7167-408e-b5eb-b3260ce186e4", "metadata": {}, "outputs": [], "source": [ "column = (20, 30)\n", "signal_index = data.wrapper.index[np.flatnonzero(exits[column])[-1]]\n", "plot_start_index = signal_index - pd.Timedelta(days=10)\n", "sub_close = data.close[plot_start_index:]\n", "sub_exits = exits.loc[plot_start_index:, column]\n", "\n", "fig = sub_close.vbt.plot()\n", "sub_exits.vbt.signals.plot_as_exits(sub_close, fig=fig)\n", "projections = exit_ranges[column].status_closed.get_projections(\n", " start_value=sub_close.loc[signal_index],\n", " start_index=signal_index\n", ")\n", "projections.vbt.plot_projections(plot_bands=False, fig=fig).show_svg()" ] }, { "cell_type": "code", "execution_count": null, "id": "06010e28-2a21-46df-a921-0b0533137762", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.12" } }, "nbformat": 4, "nbformat_minor": 5 }