查找嵌入式时间序列矩阵与超平面相交的点

Find Points where Embedded Time Series Matrix Intersects Hyperplane

我有一个 3 维嵌入式时间序列。如何找到时间序列的 3d 矩阵与任意超平面相交的 points/coordinates (x, y, z)。问题是我没有嵌入式时间序列的方程式。我是找到离超平面最近的点并将它们投影到我的超平面上,还是找到一个点穿过另一侧到另一点的位置,然后找到该线的方程并插入我的 z 值以找到( x, y) 坐标?我的情节是这样的:

这是我当前的可复制性代码:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from teaspoon.SP.tsa_tools import takens
import seaborn as sns
from datetime import datetime
import pandas_datareader.data as pdr
sns.set_style("darkgrid")

def fetch_data(symbol, from_date, to_date, cols_to_drop):
    """ Fetch OHLC data."""
    df = pdr.DataReader(symbol, "yahoo", from_date, to_date)
    df.drop(columns=cols_to_drop, inplace=True)

    return df

if __name__ == "__main__":

    # Fetch OHLC Data #
    symbol = "EURUSD=X"  # ticker
    from_date = datetime(2000, 1, 1)
    to_date = datetime.now()
    drop_columns = ["Adj Close", "Volume"]

    df = fetch_data(symbol=symbol, from_date=from_date,
                    to_date=to_date, cols_to_drop=drop_columns)

    # TAKEN'S EMBEDDING THEOREM #
    taken_matrix = takens(np.array(df.Close), n=3, tau=62) # emb_dim =3, time delay=62

    x_min, x_max = np.min(taken_matrix[:, 0]), np.max(taken_matrix[:, 0])  # x_min and x_max
    y_min, y_max = np.min(taken_matrix[:, 1]), np.max(taken_matrix[:, 1])  # y_min and y_max
    z_min, z_max = np.min(taken_matrix[:, 2]), np.max(taken_matrix[:, 2])  # z_min and z_max
    
    # Method 1
    x = np.array([x_min, x_max])
    y = np.array([y_min, y_max])
    xx, yy = np.meshgrid(x, y)
    z = np.array([[1.4, 1.4], [1.4, 1.4]])

    hyperplane = np.array([xx, yy, z])
    hyperplane = np.reshape(hyperplane.T, (4, 3))  # 4 co-ords

    fig = plt.figure(dpi=50)
    ax = plt.axes(projection="3d")
    ax.set_xlabel("x"); ax.set_ylabel("y"); ax.set_zlabel("z")
    ax.plot(taken_matrix[:, 0], taken_matrix[:, 1], taken_matrix[:, 2], c="black", lw=0.6, alpha=0.8)  # phase space
    ax.plot_surface(xx, yy, z, alpha=0.2, color="seagreen")  # Hyperplane
    plt.show()

    # Method 2
    hyperplane1 = hyperplane[:-1, :]  # 3 coordinates
    p0, p1, p2 = hyperplane1
    x0, y0, z0 = p0
    x1, y1, z1 = p1
    x2, y2, z2 = p2

    ux, uy, uz = u = [x1 - x0, y1 - y0, z1 - z0]  # first vector
    vx, vy, vz = v = [x2 - x0, y2 - y0, z2 - z0]  # second vector
    u_cross_v = [uy*vz - uz*vy, uz*vx - ux*vz, ux*vy - uy*vx]  # cross product

    point1 = np.array(p1)
    normal1 = np.array(u_cross_v)  # hyerplane normal vector

    d1 = -point1.dot(normal1)  # computed for equation of plane
    print('plane equation:\n{:1.4f}x + {:1.4f}y + {:1.4f}z + {:1.4f} = 0'.format(normal1[0], normal1[1], normal1[2], d1))

    xx, yy = np.meshgrid(x, y)
    z1 = (-normal1[0] * xx - normal1[1] * yy - d1) * 1. / normal1[2]

    fig = plt.figure()
    ax = plt.axes(projection="3d")
    ax.plot_surface(xx, yy, z1, color="orange")
    ax.plot(taken_matrix[:, 0], taken_matrix[:, 1], taken_matrix[:, 2], c="black", lw=0.6, alpha=0.8)
    plt.show()

所以这是我的解决方案,用于查找从任意超平面上方到下方通过的点的交点。在我的代码中,在我创建了 taken 矩阵之后,这是我的新实现:

    x = np.array([1, 1.6])
    y = ([1, 1.6])
    xx, yy = np.meshgrid(x, y)
    z = np.array([[1, 1.3], [1.3, 1.6]])

    hyperplane = np.array([xx, yy, z])
    hyperplane2 = np.reshape(hyperplane.T, (4, 3))
    hyperplane2 = hyperplane2[:-1, :]  # we only need 3 points

    p0, p1, p2 = hyperplane2
    x0, y0, z0 = p0
    x1, y1, z1 = p1
    x2, y2, z2 = p2

    ux, uy, uz = u = [x1 - x0, y1 - y0, z1 - z0]  # first vector
    vx, vy, vz = v = [x2 - x0, y2 - y0, z2 - z0]  # second vector
    u_cross_v = [uy*vz - uz*vy, uz*vx - ux*vz, ux*vy - uy*vx]  # cross product

    point1 = np.array(p1)
    normal1 = np.array(u_cross_v)
    d1 = -point1.dot(normal1)
    print('\nplane equation:\n{:1.4f}x + {:1.4f}y + {:1.4f}z + {:1.4f} = 0'.format(normal1[0], normal1[1], normal1[2], d1))

    xx, yy = np.meshgrid(x, y)
    z1 = (-normal1[0] * xx - normal1[1] * yy - d1) * 1. / normal1[2]

    from sympy import symbols, Eq
    from sympy.solvers import solve

    t = symbols("t")
    x, y, z = symbols("x, y, z")
    g = symbols("g")

    plane = Eq(normal1[0] * x + normal1[1] * y + normal1[2] * z + d1, g)  # create plane
    print(plane)

    # Points that pass from above to below the plane (not below to above because I want it to be transveral)
    above_or_below = np.array([solve(plane.subs([(x, taken_matrix[i][0]),
                                                 (y, taken_matrix[i][1]),
                                                 (z, taken_matrix[i][2])]), g) \
                               for i in tqdm(range(len(taken_matrix)))])

    above1, below1 = [], []
    for i in tqdm(range(1, len(above_or_below))):
        if above_or_below[i-1] >= 0 and above_or_below[i] < 0:
            above1.append(taken_matrix[i-1])
            below1.append(taken_matrix[i])
    above1 = np.array(above1)
    below1 = np.array(below1)

    # Parametric Equations for x_coords, y_coords and z_coords
    xs1 = [Eq((above1[i][0] - below1[i][0])*t + below1[i][0] - x, 0) for i in range(len(above1))]
    ys1 = [Eq((above1[i][1] - below1[i][1])*t + below1[i][1] - y, 0) for i in range(len(above1))]
    zs1 = [Eq((above1[i][2] - below1[i][2])*t + below1[i][2] - z, 0) for i in range(len(above1))]

    # Solve Equations
    xs1 = np.array([solve(i, x) for i in xs1])
    ys1 = np.array([solve(i, y) for i in ys1])
    zs1 = np.array([solve(i, z) for i in zs1])
    ts1 = np.array([solve(plane.subs([(g, 0), (x, np.squeeze(i)),
                                      (y, np.squeeze(j)), (z, np.squeeze(k))]), t) \
                    for i, j, k in zip(xs1, ys1, zs1)])  # plug x, y and z eqn's into plane to get t

    # Get x, y and z co-ordinates
    xs1 = np.array([solve(Eq(np.squeeze(i), x).subs(t, np.squeeze(j)), x) for i, j in zip(xs1, ts1)])
    ys1 = np.array([solve(Eq(np.squeeze(i), y).subs(t, np.squeeze(j)), y) for i, j in zip(ys1, ts1)])
    zs1 = np.array([solve(Eq(np.squeeze(i), z).subs(t, np.squeeze(j)), z) for i, j in zip(zs1, ts1)])

    points_on_plane1 = np.concatenate([xs1, ys1, zs1], axis=1)  # put coordinates together

    fig = plt.figure()
    ax = plt.axes(projection="3d")
    ax.plot_surface(xx, yy, z1, alpha=0.2, color="seagreen")
    ax.plot(taken_matrix[:, 0], taken_matrix[:, 1], taken_matrix[:, 2], c="black", lw=0.6, alpha=0.5)
    ax.scatter(points_on_plane1[:, 0], points_on_plane1[:, 1], points_on_plane1[:, 2], c="red")
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.set_zlabel("z")
    plt.show()