Files
strategy-lab/to_explore/notebooks/PatternsProjections.ipynb

67 KiB

Patterns and projections

Patterns

In [ ]:
from vectorbtpro import *
# whats_imported()

vbt.settings.set_theme("dark")
In [ ]:
data = vbt.BinanceData.pull(
    "BTCUSDT", 
    start="2020-06-01 UTC", 
    end="2022-06-01 UTC"
)
data.plot().show_svg()
In [ ]:
data_window = data.loc["2021-09-25":"2021-11-25"]
data_window.plot(plot_volume=False).show_svg()
In [ ]:
price_window = data_window.hlc3
price_window.vbt.plot().show_svg()
In [ ]:
pattern = np.array([1, 2, 3, 2, 3, 2])
pd.Series(pattern).vbt.plot().show_svg()

Interpolation

Linear

In [ ]:
resized_pattern = vbt.nb.interp_resize_1d_nb(
    pattern, 10, vbt.enums.InterpMode.Linear
)
resized_pattern
In [ ]:
def plot_linear(n):
    resized_pattern = vbt.nb.interp_resize_1d_nb(
        pattern, n, vbt.enums.InterpMode.Linear
    )
    return pd.Series(resized_pattern).vbt.plot()
In [ ]:
plot_linear(7).show_svg()
In [ ]:
resized_pattern = vbt.nb.interp_resize_1d_nb(
    pattern, 7, vbt.enums.InterpMode.Linear
)
ratio = (len(pattern) - 1) / (len(resized_pattern) - 1)
new_points = np.arange(len(resized_pattern)) * ratio
fig = pd.Series(pattern).vbt.plot()
pd.Series(resized_pattern, index=new_points).vbt.scatterplot(fig=fig).show_svg()

Nearest

In [ ]:
resized_pattern = vbt.nb.interp_resize_1d_nb(
    pattern, 10, vbt.enums.InterpMode.Nearest
)
resized_pattern
In [ ]:
def plot_nearest(n):
    resized_pattern = vbt.nb.interp_resize_1d_nb(
        pattern, n, vbt.enums.InterpMode.Nearest
    )
    return pd.Series(resized_pattern).vbt.plot()
In [ ]:
plot_nearest(7).show_svg()

Discrete

In [ ]:
resized_pattern = vbt.nb.interp_resize_1d_nb(
    pattern, 10, vbt.enums.InterpMode.Discrete
)
resized_pattern
In [ ]:
def plot_discrete(n):
    resized_pattern = vbt.nb.interp_resize_1d_nb(
        pattern, n, vbt.enums.InterpMode.Discrete
    )
    return pd.Series(resized_pattern).vbt.plot(
        trace_kwargs=dict(
            line=dict(dash="dot"), 
            connectgaps=True
        )
    )
In [ ]:
plot_discrete(7).show_svg()

Mixed

In [ ]:
resized_pattern = vbt.nb.interp_resize_1d_nb(
    pattern, 10, vbt.enums.InterpMode.Mixed
)
resized_pattern
In [ ]:
def plot_mixed(n):
    lin_resized_pattern = vbt.nb.interp_resize_1d_nb(
        pattern, n, vbt.enums.InterpMode.Linear
    )
    mix_resized_pattern = vbt.nb.interp_resize_1d_nb(
        pattern, n, vbt.enums.InterpMode.Mixed
    )
    fig = pd.Series(lin_resized_pattern, name="Linear").vbt.plot()
    return pd.Series(mix_resized_pattern, name="Mixed").vbt.plot(fig=fig)
In [ ]:
plot_mixed(7).show_svg()
In [ ]:
resized_pattern = vbt.nb.interp_resize_1d_nb(
    pattern, len(price_window), vbt.enums.InterpMode.Mixed
)
resized_pattern.shape

Rescaling

In [ ]:
pattern_scale = (resized_pattern.min(), resized_pattern.max())
price_window_scale = (price_window.min(), price_window.max())
rescaled_pattern = vbt.utils.array_.rescale_nb(
    resized_pattern, pattern_scale, price_window_scale
)
rescaled_pattern = pd.Series(rescaled_pattern, index=price_window.index)
In [ ]:
fig = price_window.vbt.plot()
rescaled_pattern.vbt.plot(
    trace_kwargs=dict(
        fill="tonexty", 
        fillcolor="rgba(255, 100, 0, 0.25)"
    ), 
    fig=fig
).show_svg()

Rebasing

In [ ]:
pct_pattern = np.array([1, 1.3, 1.6, 1.3, 1.6, 1.3])
resized_pct_pattern = vbt.nb.interp_resize_1d_nb(
    pct_pattern, len(price_window), vbt.enums.InterpMode.Mixed
)
rebased_pattern = resized_pct_pattern / resized_pct_pattern[0]
rebased_pattern *= price_window.values[0]
rebased_pattern = pd.Series(rebased_pattern, index=price_window.index)
fig = price_window.vbt.plot()
rebased_pattern.vbt.plot(
    trace_kwargs=dict(
        fill="tonexty", 
        fillcolor="rgba(255, 100, 0, 0.25)"
    ), 
    fig=fig
).show_svg()

Similarity

In [ ]:
abs_distances = np.abs(rescaled_pattern - price_window.values)
mae = abs_distances.sum()
max_abs_distances = np.column_stack((
    (price_window.max() - rescaled_pattern), 
    (rescaled_pattern - price_window.min())
)).max(axis=1)
max_mae = max_abs_distances.sum()
similarity = 1 - mae / max_mae
similarity
In [ ]:
quad_distances = (rescaled_pattern - price_window.values) ** 2
rmse = np.sqrt(quad_distances.sum())
max_quad_distances = np.column_stack((
    (price_window.max() - rescaled_pattern), 
    (rescaled_pattern - price_window.min())
)).max(axis=1) ** 2
max_rmse = np.sqrt(max_quad_distances.sum())
similarity = 1 - rmse / max_rmse
similarity
In [ ]:
quad_distances = (rescaled_pattern - price_window.values) ** 2
mse = quad_distances.sum()
max_quad_distances = np.column_stack((
    (price_window.max() - rescaled_pattern), 
    (rescaled_pattern - price_window.min())
)).max(axis=1) ** 2
max_mse = max_quad_distances.sum()
similarity = 1 - mse / max_mse
similarity
In [ ]:
vbt.nb.pattern_similarity_nb(price_window.values, pattern)
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pct_pattern, 
    rescale_mode=vbt.enums.RescaleMode.Rebase
)
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pct_pattern, 
    interp_mode=vbt.enums.InterpMode.Nearest,
    rescale_mode=vbt.enums.RescaleMode.Rebase,
    distance_measure=vbt.enums.DistanceMeasure.RMSE
)
In [ ]:
price_window.vbt.plot_pattern(
    pct_pattern, 
    interp_mode="nearest",
    rescale_mode="rebase",
    fill_distance=True
).show_svg()
In [ ]:
adj_pct_pattern = np.array([1, 1.3, 1.6, 1.45, 1.6, 1.3])
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    adj_pct_pattern, 
    interp_mode=vbt.enums.InterpMode.Nearest,
    rescale_mode=vbt.enums.RescaleMode.Rebase,
    distance_measure=vbt.enums.DistanceMeasure.RMSE
)
In [ ]:
price_window.vbt.plot_pattern(
    adj_pct_pattern, 
    interp_mode="discrete",
    rescale_mode="rebase",
).show_svg()
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    adj_pct_pattern, 
    interp_mode=vbt.enums.InterpMode.Discrete,
    rescale_mode=vbt.enums.RescaleMode.Rebase,
    distance_measure=vbt.enums.DistanceMeasure.RMSE
)

Relative

In [ ]:
abs_pct_distances = abs_distances / rescaled_pattern
pct_mae = abs_pct_distances.sum()
max_abs_pct_distances = max_abs_distances / rescaled_pattern
max_pct_mae = max_abs_pct_distances.sum()
similarity = 1 - pct_mae / max_pct_mae
similarity
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pct_pattern, 
    error_type=vbt.enums.ErrorType.Relative
)
In [ ]:
vbt.nb.pattern_similarity_nb(
    np.array([10, 30, 100]),
    np.array([1, 2, 3]),
    error_type=vbt.enums.ErrorType.Absolute
)
In [ ]:
vbt.nb.pattern_similarity_nb(
    np.array([10, 30, 100]),
    np.array([1, 2, 3]),
    error_type=vbt.enums.ErrorType.Relative
)

Inverse

In [ ]:
vbt.nb.pattern_similarity_nb(price_window.values, pattern, invert=True)
In [ ]:
price_window.vbt.plot_pattern(pattern, invert=True).show_svg()
In [ ]:
pattern.max() + pattern.min() - pattern

Max error

In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pattern,
)
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pattern, 
    max_error=np.array([0.5, 0.5, 0.5, 0.5, 0.5, 0.5]),
)
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pattern, 
    max_error=np.array([0.5]),
)
In [ ]:
price_window.vbt.plot_pattern(
    pattern, 
    max_error=0.5
).show_svg()
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pattern, 
    max_error=np.array([0.5]),
    max_error_strict=True
)
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    adj_pct_pattern, 
    rescale_mode=vbt.enums.RescaleMode.Rebase,
    max_error=np.array([0.2, 0.1, 0.05, 0.1, 0.05, 0.1]),
    max_error_strict=True
)
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pattern, 
    max_error=np.array([0.1]),
    error_type=vbt.enums.ErrorType.Relative
)
In [ ]:
price_window.vbt.plot_pattern(
    pattern, 
    max_error=0.1,
    error_type="relative"
).show_svg()
In [ ]:
price_window.vbt.plot_pattern(
    adj_pct_pattern, 
    rescale_mode="rebase",
    max_error=np.array([0.2, 0.1, 0.05, 0.1, 0.05, 0.1])
).show_svg()
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    adj_pct_pattern, 
    rescale_mode=vbt.enums.RescaleMode.Rebase,
    max_error=np.array([0.2, 0.1, 0.05, 0.1, 0.05, 0.1]) + 0.05,
    max_error_strict=True
)
Interpolation
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    adj_pct_pattern, 
    rescale_mode=vbt.enums.RescaleMode.Rebase,
    max_error=np.array([np.nan, np.nan, 0.1, np.nan, 0.1, np.nan]),
    max_error_interp_mode=vbt.enums.InterpMode.Discrete,
    max_error_strict=True
)
In [ ]:
price_window.vbt.plot_pattern(
    adj_pct_pattern, 
    rescale_mode="rebase",
    max_error=np.array([np.nan, np.nan, 0.1, np.nan, 0.1, np.nan]),
    max_error_interp_mode="discrete"
).show_svg()
Max distance
In [ ]:
vbt.nb.pattern_similarity_nb(price_window.values, pattern)
In [ ]:
vbt.nb.pattern_similarity_nb(
    price_window.values, 
    pattern, 
    max_error=np.array([0.5]),
    max_error_as_maxdist=True
)

Further filters

In [ ]:
vbt.nb.pattern_similarity_nb(price_window.values, pattern, max_pct_change=0.3)
In [ ]:
vbt.nb.pattern_similarity_nb(price_window.values, pattern, min_similarity=0.9)

Rolling similarity

In [ ]:
price = data.hlc3

similarity = price.vbt.rolling_pattern_similarity(
    pattern, 
    window=30,
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete"
)
similarity.describe()
In [ ]:
end_row = similarity.argmax() + 1
start_row = end_row - 30
fig = data.iloc[start_row:end_row].plot(plot_volume=False)
price.iloc[start_row:end_row].vbt.plot_pattern(
    pattern, 
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete",
    plot_obj=False, 
    fig=fig
).show_svg()
In [ ]:
end_row = similarity.argmin() + 1
start_row = end_row - 30
fig = data.iloc[start_row:end_row].plot(plot_volume=False)
price.iloc[start_row:end_row].vbt.plot_pattern(
    pattern, 
    invert=True,
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete",
    plot_obj=False, 
    fig=fig
).show_svg()
In [ ]:
inv_similarity = price.vbt.rolling_pattern_similarity(
    pattern, 
    window=30,
    invert=True,
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete"
)
inv_similarity.describe()
In [ ]:
end_row = inv_similarity.argmax() + 1
start_row = end_row - 30
fig = data.iloc[start_row:end_row].plot(plot_volume=False)
price.iloc[start_row:end_row].vbt.plot_pattern(
    pattern, 
    invert=True,
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete",
    plot_obj=False, 
    fig=fig
).show_svg()

Indicator

In [ ]:
patsim = vbt.PATSIM.run(
    price, 
    vbt.Default(pattern),
    error_type=vbt.Default("relative"),
    max_error=vbt.Default(0.05),
    max_error_interp_mode=vbt.Default("discrete"),
    window=[30, 45, 60, 75, 90]
)
In [ ]:
patsim.wrapper.columns
In [ ]:
patsim.plot(column=60).show_svg()
In [ ]:
patsim.overlay_with_heatmap(column=60).show_svg()
In [ ]:
exits = patsim.similarity >= 0.8
exits.sum()
In [ ]:
patsim = vbt.PATSIM.run(
    price, 
    vbt.Default(pattern),
    error_type=vbt.Default("relative"),
    max_error=vbt.Default(0.05),
    max_error_interp_mode=vbt.Default("discrete"),
    window=[30, 45, 60, 75, 90],
    invert=[False, True],
    min_similarity=[0.7, 0.8],
    param_product=True
)
exits = ~patsim.similarity.isnull()
exits.sum()
In [ ]:
groupby = [
    name for name in patsim.wrapper.columns.names 
    if name != "patsim_window"
]
max_sim = patsim.similarity.groupby(groupby, axis=1).max()
entries = ~max_sim.xs(True, level="patsim_invert", axis=1).isnull()
exits = ~max_sim.xs(False, level="patsim_invert", axis=1).isnull()
In [ ]:
fig = data.plot(ohlc_trace_kwargs=dict(opacity=0.5))
entries[0.8].vbt.signals.plot_as_entries(price, fig=fig)
exits[0.8].vbt.signals.plot_as_exits(price, fig=fig).show_svg()
In [ ]:
pattern_range_records = vbt.nb.find_pattern_1d_nb(
    price.values,
    pattern,
    window=30,
    max_window=90,
    error_type=vbt.enums.ErrorType.Relative,
    max_error=np.array([0.05]),
    max_error_interp_mode=vbt.enums.InterpMode.Discrete,
    min_similarity=0.85
)
pattern_range_records
In [ ]:
start_row = pattern_range_records[1]["start_idx"]
end_row = pattern_range_records[1]["end_idx"]
fig = data.iloc[start_row:end_row + 30].plot(plot_volume=False)
price.iloc[start_row:end_row].vbt.plot_pattern(
    pattern, 
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete",
    plot_obj=False, 
    fig=fig
).show_svg()
In [ ]:
pattern_ranges = vbt.PatternRanges.from_pattern_search(
    price,
    pattern,
    window=30,
    max_window=120,
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete",
    min_similarity=0.85
)
pattern_ranges
In [ ]:
pattern_ranges = price.vbt.find_pattern(
    pattern,
    window=30,
    max_window=90,
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete",
    min_similarity=0.85
)
In [ ]:
print(pattern_ranges.records_readable)
In [ ]:
pattern_ranges.wrapper.columns
In [ ]:
pattern_ranges.search_configs
In [ ]:
pattern_ranges.plot().show_svg()
In [ ]:
pattern_ranges.loc["2021-09-01":"2022-01-01"].plot().show_svg()
In [ ]:
pattern_ranges.stats()

Overlapping

In [ ]:
pattern_ranges = price.vbt.find_pattern(
    pattern,
    window=30,
    max_window=120,
    error_type="relative",
    max_error=0.05,
    max_error_interp_mode="discrete",
    min_similarity=0.85,
    overlap_mode="allow"
)
In [ ]:
pattern_ranges.count()
In [ ]:
pattern_ranges.overlap_coverage
In [ ]:
pattern_ranges.plot(plot_zones=False, plot_patterns=False).show_svg()

Random selection

In [ ]:
def run_prob_search(row_select_prob, window_select_prob):
    return price.vbt.find_pattern(
        pattern,
        window=30,
        max_window=120,
        row_select_prob=row_select_prob,
        window_select_prob=window_select_prob,
        error_type="relative",
        max_error=0.05,
        max_error_interp_mode="discrete",
        min_similarity=0.8,
    )
In [ ]:
%timeit run_prob_search(1.0, 1.0)
In [ ]:
%timeit run_prob_search(0.5, 0.25)
In [ ]:
run_prob_search(1.0, 1.0).count()
In [ ]:
pd.Series([
    run_prob_search(0.5, 0.25).count() 
    for i in range(100)
]).vbt.plot().show_svg()

Params

In [ ]:
pattern_ranges = price.vbt.find_pattern(
    vbt.Param([
        [1, 2, 1],
        [2, 1, 2],
        [1, 2, 3],
        [3, 2, 1]
    ]),
    window=30,
    max_window=120,
)
In [ ]:
pattern_ranges.count()
In [ ]:
pattern_ranges = price.vbt.find_pattern(
    vbt.Param([
        [1, 2, 1],
        [2, 1, 2],
        [1, 2, 3],
        [3, 2, 1]
    ], keys=["v-top", "v-bottom", "rising", "falling"]),
    window=30,
    max_window=120,
)
pattern_ranges.count()
In [ ]:
pattern_ranges.plot(column="falling").show_svg()
In [ ]:
pattern_ranges = price.vbt.find_pattern(
    vbt.Param([
        [1, 2, 1],
        [2, 1, 2],
        [1, 2, 3],
        [3, 2, 1]
    ], keys=["v-top", "v-bottom", "rising", "falling"]),
    window=30,
    max_window=120,
    min_similarity=vbt.Param([0.8, 0.85])
)
pattern_ranges.count()
In [ ]:
pattern_ranges.plot(column=("v-bottom", 0.8)).show_svg()
In [ ]:
pattern_ranges = price.vbt.find_pattern(
    vbt.Param([
        [1, 2, 1],
        [2, 1, 2],
        [1, 2, 3],
        [3, 2, 1]
    ], keys=["v-top", "v-bottom", "rising", "falling"], level=0),
    window=vbt.Param([30, 30, 7, 7], level=0),
    max_window=vbt.Param([120, 120, 30, 30], level=0),
    min_similarity=vbt.Param([0.8, 0.85], level=1)
)
pattern_ranges.count()

Configs

In [ ]:
mult_data = vbt.BinanceData.pull(
    ["BTCUSDT", "ETHUSDT"], 
    start="2020-06-01 UTC", 
    end="2022-06-01 UTC"
)
mult_price = mult_data.hlc3
In [ ]:
pattern_ranges = mult_price.vbt.find_pattern(
    search_configs=[
        vbt.PSC(pattern=[1, 2, 3, 2, 3, 2], window=30),
        [
            vbt.PSC(pattern=mult_price.iloc[-30:, 0]),
            vbt.PSC(pattern=mult_price.iloc[-30:, 1]),
        ]
    ],
    min_similarity=0.8
)
pattern_ranges.count()
In [ ]:
pattern_ranges = mult_price.vbt.find_pattern(
    search_configs=[
        vbt.PSC(pattern=[1, 2, 3, 2, 3, 2], window=30, name="double_top"),
        [
            vbt.PSC(pattern=mult_price.iloc[-30:, 0], name="last"),
            vbt.PSC(pattern=mult_price.iloc[-30:, 1], name="last"),
        ]
    ],
    min_similarity=0.8
)
pattern_ranges.count()
In [ ]:
pattern_ranges = mult_price.vbt.find_pattern(
    search_configs=[
        vbt.PSC(pattern=[1, 2, 3, 2, 3, 2], window=30, name="double_top"),
        [
            vbt.PSC(pattern=mult_price.iloc[-30:, 0], name="last"),
            vbt.PSC(pattern=mult_price.iloc[-30:, 1], name="last"),
        ]
    ],
    rescale_mode=vbt.Param(["minmax", "rebase"]),
    min_similarity=0.8,
    open=mult_data.open,
    high=mult_data.high,
    low=mult_data.low,
    close=mult_data.close,
)
pattern_ranges.count()
In [ ]:
pattern_ranges.plot(column=("rebase", "last", "ETHUSDT")).show_svg()

Mask

In [ ]:
mask = pattern_ranges.last_pd_mask
mask.sum()

Indicator

In [ ]:
pattern_ranges = price.vbt.find_pattern(
    pattern,
    window=30,
    max_window=120,
    row_select_prob=0.5,
    window_select_prob=0.5,
    overlap_mode="allow",
    seed=42
)
pr_mask = pattern_ranges.map_field(
    "similarity", 
    idx_arr=pattern_ranges.last_idx.values
).to_pd()
pr_mask[~pr_mask.isnull()]
In [ ]:
patsim = vbt.PATSIM.run(
    price,
    vbt.Default(pattern),
    window=vbt.Default(30),
    max_window=vbt.Default(120),
    row_select_prob=vbt.Default(0.5),
    window_select_prob=vbt.Default(0.5),
    min_similarity=vbt.Default(0.85),
    seed=42
)
ind_mask = patsim.similarity
ind_mask[~ind_mask.isnull()]

Combination

In [ ]:
price_highs = vbt.PATSIM.run(
    data.high, 
    pattern=np.array([1, 3, 2, 4]), 
    window=40,
    max_window=50
)
macd = data.run("talib_macd").macd
macd_lows = vbt.PATSIM.run(
    macd, 
    pattern=np.array([4, 2, 3, 1]), 
    window=40,
    max_window=50
)

fig = vbt.make_subplots(
    rows=3, cols=1, shared_xaxes=True, vertical_spacing=0.02
)
fig.update_layout(height=500)
data.high.rename("Price").vbt.plot(
    add_trace_kwargs=dict(row=1, col=1), fig=fig
)
macd.rename("MACD").vbt.plot(
    add_trace_kwargs=dict(row=2, col=1), fig=fig
)
price_highs.similarity.rename("Price Sim").vbt.plot(
    add_trace_kwargs=dict(row=3, col=1), fig=fig
)
macd_lows.similarity.rename("MACD Sim").vbt.plot(
    add_trace_kwargs=dict(row=3, col=1), fig=fig
)
fig.show_svg()
In [ ]:
cond1 = (price_highs.similarity >= 0.8).vbt.rolling_any(10)
cond2 = (macd_lows.similarity >= 0.8).vbt.rolling_any(10)
exits = cond1 & cond2
fig = data.plot(ohlc_trace_kwargs=dict(opacity=0.5))
exits.vbt.signals.plot_as_exits(data.close, fig=fig).show_svg()

Projections

In [ ]:
pattern_ranges = price.vbt.find_pattern(
    [1, 1.2], 
    window=7, 
    rescale_mode="rebase", 
    max_error=0.01,
    max_error_interp_mode="discrete",
    max_error_strict=True
)
pattern_ranges.count()

Pattern projections

In [ ]:
range_idxs, raw_projections = vbt.nb.map_ranges_to_projections_nb(
    vbt.to_2d_array(price),
    pattern_ranges.get_field_arr("col"),
    pattern_ranges.get_field_arr("start_idx"),
    pattern_ranges.get_field_arr("end_idx"),
    pattern_ranges.get_field_arr("status")
)
In [ ]:
range_idxs
In [ ]:
raw_projections
In [ ]:
projections = pattern_ranges.get_projections()
print(projections)
In [ ]:
pattern_ranges.duration.values
In [ ]:
projections = pattern_ranges.get_projections(incl_end_idx=False)
print(projections)
In [ ]:
projections.iloc[-1] / projections.iloc[0] - 1
In [ ]:
projections.vbt.plot().show_svg()

Delta projections

In [ ]:
delta_ranges = pattern_ranges.with_delta(4)
In [ ]:
fig = pattern_ranges.loc["2021-01":"2021-03"].plot()
delta_ranges.loc["2021-01":"2021-03"].plot(
    plot_ohlc=False,
    plot_close=False,
    plot_markers=False,
    closed_shape_kwargs=dict(fillcolor="DeepSkyBlue"),
    fig=fig
).show_svg()
In [ ]:
projections = delta_ranges.get_projections()
print(projections)
In [ ]:
np.mean(projections.iloc[-1] / projections.iloc[0] - 1)
In [ ]:
pattern_ranges = mult_price.vbt.find_pattern(
    [1, 1.2], 
    window=7, 
    max_window=30,
    rescale_mode="rebase",
    max_error=0.01,
    max_error_interp_mode="discrete",
    max_error_strict=True,
    overlap_mode="allow"
)
pattern_ranges.count()
In [ ]:
delta_ranges = pattern_ranges.with_delta(4)
In [ ]:
projections = delta_ranges.get_projections()
In [ ]:
(projections.iloc[-1] / projections.iloc[0] - 1).describe()
In [ ]:
projections = delta_ranges.get_projections(id_level="end_idx")
In [ ]:
print(projections.columns)
In [ ]:
btc_projections = projections.xs("BTCUSDT", level="symbol", axis=1)
total_proj_return = btc_projections.iloc[-1] / btc_projections.iloc[0] - 1
total_proj_return.vbt.scatterplot(
    trace_kwargs=dict(
        marker=dict(
            color=total_proj_return.values,
            colorscale="Temps_r",
            cmid=0
        )
    )
).show_svg()

Plotting

In [ ]:
btc_projections.vbt.plot_projections(plot_bands=False).show_svg()

Colorization

In [ ]:
btc_projections["2020-08-03"]
In [ ]:
btc_projections["2020-08-03"].median()
In [ ]:
btc_projections.vbt.plot_projections(
    plot_bands=False, colorize=np.std
).show_svg()

Bands

In [ ]:
projections.xs("ETHUSDT", level="symbol", axis=1).median(axis=1)
In [ ]:
print(projections.groupby("symbol", axis=1).median())
In [ ]:
projections.median(axis=1)
In [ ]:
btc_projections.vbt.plot_projections().show_svg()
In [ ]:
btc_projections.iloc[-1].quantile(0.8)
In [ ]:
btc_projections.vbt.plot_projections(
    plot_lower=False,
    plot_middle="30%", 
    plot_upper=False, 
    plot_aux_middle=False, 
).show_svg()
In [ ]:
btc_projections.iloc[-1].vbt.qqplot().show_svg()
In [ ]:
btc_projections.vbt.plot_projections(
    plot_lower="P=20%",
    plot_middle="mean", 
    plot_upper="P=80%", 
    plot_aux_middle=False, 
).show_svg()
In [ ]:
def finishes_at_quantile(df, q):
    nth_element = int(np.ceil(q * (df.shape[1] - 1)))
    nth_index = np.argsort(df.iloc[-1])[nth_element]
    return df.iloc[:, nth_index]

btc_projections.vbt.plot_projections(
    plot_lower=partial(finishes_at_quantile, q=0.2),
    plot_middle=False, 
    plot_upper=partial(finishes_at_quantile, q=0.8), 
).show_svg()

Filtering

In [ ]:
crossed_mask = projections.expanding().max().iloc[1] >= 1.05
filt_projections = projections.loc[:, crossed_mask]
filt_projections.iloc[-1].describe()
In [ ]:
filt_projections.vbt.plot_projections().show_svg()

Latest projections

In [ ]:
pattern_ranges = price.vbt.find_pattern(
    pattern=data.close.iloc[-7:],
    rescale_mode="rebase",
    overlap_mode="allow"
)
pattern_ranges.count()
In [ ]:
pattern_ranges = pattern_ranges.status_closed
pattern_ranges.count()
In [ ]:
projections = pattern_ranges.get_projections()
projections.vbt.plot_projections(plot_bands=False).show_svg()
In [ ]:
delta_ranges = pattern_ranges.with_delta(7)
projections = delta_ranges.get_projections(start_value=-1)
fig = data.iloc[-7:].plot(plot_volume=False)
projections.vbt.plot_projections(fig=fig).show_svg()
In [ ]:
projections.mean(axis=1)
In [ ]:
next_data = vbt.BinanceData.pull(
    "BTCUSDT", 
    start="2022-05-31", 
    end="2022-06-08"
)
next_data.close

Quick plotting

In [ ]:
delta_ranges.plot_projections().show_svg()

Non-uniform projections

In [ ]:
windows = np.arange(10, 31)
window_tuples = combinations(windows, 2)
window_tuples = filter(lambda x: abs(x[0] - x[1]) >= 5, window_tuples)
fast_windows, slow_windows = zip(*window_tuples)
fast_sma = data.run("sma", fast_windows, short_name="fast_sma")
slow_sma = data.run("sma", slow_windows, short_name="slow_sma")
entries = fast_sma.real_crossed_above(slow_sma.real)
exits = fast_sma.real_crossed_below(slow_sma.real)

entries.shape
In [ ]:
entry_ranges = entries.vbt.signals.delta_ranges(30, close=data.close)
entry_ranges = entry_ranges.status_closed
entry_ranges.count().sum()
In [ ]:
exit_ranges = exits.vbt.signals.delta_ranges(30, close=data.close)
exit_ranges = exit_ranges.status_closed
exit_ranges.count().sum()
In [ ]:
entry_projections = entry_ranges.get_projections()
entry_projections.shape
In [ ]:
exit_projections = exit_ranges.get_projections()
exit_projections.shape
In [ ]:
fig = entry_projections.vbt.plot_projections(
    plot_projections=False,
    lower_trace_kwargs=dict(name="Lower (entry)", line_color="green"),
    middle_trace_kwargs=dict(name="Middle (entry)", line_color="green"),
    upper_trace_kwargs=dict(name="Upper (entry)", line_color="green"),
    plot_aux_middle=False,
    plot_fill=False
)
fig = exit_projections.vbt.plot_projections(
    plot_projections=False,
    lower_trace_kwargs=dict(name="Lower (exit)", line_color="orangered"),
    middle_trace_kwargs=dict(name="Middle (exit)", line_color="orangered"),
    upper_trace_kwargs=dict(name="Upper (exit)", line_color="orangered"),
    plot_aux_middle=False,
    plot_fill=False,
    fig=fig
)
fig.show_svg()
In [ ]:
entry_ranges = entries.vbt.signals.between_ranges(exits, close=data.close)
entry_ranges = entry_ranges.status_closed
entry_ranges.count().sum()
In [ ]:
exit_ranges = exits.vbt.signals.between_ranges(entries, close=data.close)
exit_ranges = exit_ranges.status_closed
exit_ranges.count().sum()
In [ ]:
entry_projections = entry_ranges.get_projections()
entry_projections.shape
In [ ]:
exit_projections = exit_ranges.get_projections()
exit_projections.shape
In [ ]:
rand_cols = np.random.choice(entry_projections.shape[1], 100)
entry_projections.iloc[:, rand_cols].vbt.plot_projections(plot_bands=False).show_svg()
In [ ]:
rand_cols = np.random.choice(exit_projections.shape[1], 100)
exit_projections.iloc[:, rand_cols].vbt.plot_projections(plot_bands=False).show_svg()

Shrinking

In [ ]:
entry_projections = entry_ranges.get_projections(proj_period="30d")
entry_projections.shape
In [ ]:
exit_projections = exit_ranges.get_projections(proj_period="30d")
exit_projections.shape
In [ ]:
rand_cols = np.random.choice(entry_projections.shape[1], 100)
entry_projections.iloc[:, rand_cols].vbt.plot_projections().show_svg()
In [ ]:
rand_cols = np.random.choice(exit_projections.shape[1], 100)
exit_projections.iloc[:, rand_cols].vbt.plot_projections().show_svg()

Stretching

In [ ]:
entry_projections = entry_ranges.get_projections(
    proj_period="30d", extend=True
)
entry_projections.shape
In [ ]:
exit_projections = exit_ranges.get_projections(
    proj_period="30d", extend=True
)
exit_projections.shape
In [ ]:
rand_cols = np.random.choice(entry_projections.shape[1], 100)
entry_projections.iloc[:, rand_cols].vbt.plot_projections().show_svg()
In [ ]:
rand_cols = np.random.choice(exit_projections.shape[1], 100)
exit_projections.iloc[:, rand_cols].vbt.plot_projections().show_svg()

Quick plotting

In [ ]:
entry_ranges.wrapper.columns
In [ ]:
entry_ranges.plot_projections(
    column=(25, 30),
    last_n=10,
    proj_period="30d", 
    extend=True,
    plot_lower=False,
    plot_upper=False,
    plot_aux_middle=False,
    projection_trace_kwargs=dict(opacity=0.3)
).show_svg()

Open projections

In [ ]:
exit_ranges = exits.vbt.signals.between_ranges(
    entries, 
    incl_open=True, 
    close=data.close
)
exit_ranges.count().sum()
In [ ]:
exit_ranges.wrapper.columns[exit_ranges.status_open.col_arr]
In [ ]:
exit_ranges.status_closed.plot_projections(
    column=(20, 30), plot_bands=False
).show_svg()
In [ ]:
exit_ranges.plot_projections(
    column=(20, 30), plot_bands=False
).show_svg()
In [ ]:
column = (20, 30)
signal_index = data.wrapper.index[np.flatnonzero(exits[column])[-1]]
plot_start_index = signal_index - pd.Timedelta(days=10)
sub_close = data.close[plot_start_index:]
sub_exits = exits.loc[plot_start_index:, column]

fig = sub_close.vbt.plot()
sub_exits.vbt.signals.plot_as_exits(sub_close, fig=fig)
projections = exit_ranges[column].status_closed.get_projections(
    start_value=sub_close.loc[signal_index],
    start_index=signal_index
)
projections.vbt.plot_projections(plot_bands=False, fig=fig).show_svg()
In [ ]: