Matplotlib строит рынок между тиками (ось X) - PullRequest
2 голосов
/ 06 января 2020

Я вычисляю 2 скользящие средние по цене акций и нахожу, что они пересеклись. Когда они пересекаются, я хочу показать на графике маркер поверх него.

Чтобы найти кроссоверы, я использую этот код:

idxs = np.argwhere(np.diff(df_status)).flatten()

, где df_status - список с -1, 0 и 1 от двух скользящих средних. Idxs дает мне позицию индекса из df_status, где произошло пересечение.

Проблема в том, что пересечение находится между двумя датами, как показано на рисунке ниже: crossover between SMA 10 and 100. Blue line is stock price

Как я могу переместить маркер по центру на пересечении, чем в дату, когда он был обнаружен?

Код для воспроизведения:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

data = [
    ["2019-12-16", 4.39, 4.02, 5.11],
    ["2019-12-17", 4.42, 4.08, 5.09],
    ["2019-12-18", 4.2, 4.11, 5.06],
    ["2019-12-19", 4.57, 4.18, 5.04],
    ["2019-12-20", 4.85, 4.27, 5.03],
    ["2019-12-23", 4.95, 4.36, 5.01],
    ["2019-12-26", 5.8, 4.54, 5.01],
    ["2019-12-27", 6.0, 4.74, 5.01],
    ["2019-12-30", 5.9, 4.92, 5.0],
    ["2020-01-02", 6.02, 5.11, 5.00]
]
columns = ["day", "price", "SMA_10", "SMA_100"]

df = pd.DataFrame(data, columns=columns)
df['status_SMA_10_SMA_100'] = np.sign(df['SMA_10'] - df['SMA_100'])
idxs = np.argwhere(np.diff(df['status_SMA_10_SMA_100'])).flatten() # get crossovers

fig = plt.figure(figsize=[15, 8])
ax = fig.gca()
plt.grid(True)
plt.plot(df['day'], df['price'])
plt.plot(df['day'], df['SMA_10'])
plt.plot(df['day'], df['SMA_100'])
for marker in idxs:
    ax.plot(df['day'][marker], df['SMA_100'][marker], marker='o', markersize=35, alpha=.5)
    ax.plot(df['day'][marker + 1], df['SMA_100'][marker], marker='o', markersize=35, alpha=.5)
plt.show()

В этом коде пересечение с индексом 8, но на графике происходит пересечение между индексами 8 и 9. Как я могу расположить маркер между двумя отметками X?

Ответы [ 2 ]

2 голосов
/ 06 января 2020

IIU C, чтобы найти кроссовер 'SMA_10' и 'SMA_100', попробуйте это:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

data = [
    ["2019-12-16", 4.39, 4.02, 5.11],
    ["2019-12-17", 4.42, 4.08, 5.09],
    ["2019-12-18", 4.2, 4.11, 5.06],
    ["2019-12-19", 4.57, 4.18, 5.04],
    ["2019-12-20", 4.85, 4.27, 5.03],
    ["2019-12-23", 4.95, 4.36, 5.01],
    ["2019-12-26", 5.8, 4.54, 5.01],
    ["2019-12-27", 6.0, 4.74, 5.01],
    ["2019-12-30", 5.9, 4.92, 5.0],
    ["2020-01-02", 6.02, 5.11, 5.00]
]
columns = ["day", "price", "SMA_10", "SMA_100"]

df = pd.DataFrame(data, columns=columns)
df['status_SMA_10_SMA_100'] = np.sign(df['SMA_10'] - df['SMA_100'])
idxs = np.argwhere(np.diff(df['status_SMA_10_SMA_100'])).flatten() # get crossovers

fig = plt.figure(figsize=[15, 8])
ax = fig.gca()
plt.grid(True)
plt.plot(df['day'], df['price'])
plt.plot(df['day'], df['SMA_10'])
plt.plot(df['day'], df['SMA_100'])
s = (df['SMA_10'] - df['SMA_100']).reset_index().set_index(0)
xmarker = s.reindex(s.index.union([0])).interpolate(method='index').loc[0.00].values
ymarker = df['SMA_10'].reindex(df.index.union(xmarker)).interpolate(method='index').loc[xmarker].values
ax.plot(xmarker, ymarker, marker='o', markersize='35', alpha=.5)
# for marker in idxs:
#     ax.plot(df['day'][marker], df['SMA_100'][marker], marker='o', markersize=35, alpha=.5)
#     ax.plot(df['day'][marker + 1], df['SMA_100'][marker], marker='o', markersize=35, alpha=.5)
plt.show()

Выход:

enter image description here

1 голос
/ 10 января 2020

Используя предложение @ScottBoston, я пришел к этому решению, которое работает с одним и несколькими кроссоверами:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg


def getAxisPositionForCrosses(index_position, df):
    qtt_points = 10
    ma1 = [np.nan] * qtt_points
    ma1[0] = df.loc[index_position]['SMA_10']
    ma1[qtt_points - 1] = df.loc[index_position + 1]['SMA_10']
    ma2 = [np.nan] * qtt_points
    ma2[0] = df.loc[index_position]['SMA_100']
    ma2[qtt_points - 1] = df.loc[index_position + 1]['SMA_100']

    df_cross = pd.DataFrame({'ma1': ma1, 'ma2': ma2})
    df_cross = df_cross.interpolate(method='index')
    df_cross['diff'] = df_cross['ma1'] >= df_cross['ma2']
    idxs_crosses = np.argwhere(np.diff(df_cross['diff'])).flatten()
    x_cross = index_position + 1/idxs_crosses[0]
    return {'x': x_cross, 'y': df_cross.loc[idxs_crosses[0]]['ma2']}

data = [
    ["2019-12-17", 8.54, 8.73, 8.68],
    ["2019-12-18", 8.4, 8.69, 8.66],
    ["2019-12-19", 8.41, 8.66, 8.65],
    ["2019-12-20", 8.09, 8.6, 8.62],
    ["2019-12-23", 8.4, 8.58, 8.61],
    ["2019-12-26", 8.25, 8.54, 8.58],
    ["2019-12-27", 8.42, 8.53, 8.58],
    ["2019-12-30", 8.78, 8.55, 8.59],
    ["2020-01-02", 8.97, 8.6, 8.61],
    ["2020-01-03", 9.27, 8.68, 8.65]
]
columns = ["day", "price", "SMA_10", "SMA_100"]

df = pd.DataFrame(data, columns=columns)
df['status_SMA_10_SMA_100'] = np.sign(df['SMA_10'] - df['SMA_100'])
# get crossovers
idxs = np.argwhere(np.diff(df['status_SMA_10_SMA_100'])).flatten()
cross_x = []
cross_y = []
for index in idxs:
    cross = getAxisPositionForCrosses(index, df)
    cross_x.append(cross['x'])
    cross_y.append(cross['y'])

fig = plt.figure(figsize=[15, 8])
ax = fig.gca()
plt.grid(True)
plt.plot(df['day'], df['price'])
plt.plot(df['day'], df['SMA_10'])
plt.plot(df['day'], df['SMA_100'])
ax.plot([cross_x], [cross_y], marker='o', markersize='35', alpha=.5)
plt.show()

Multiple crossovers Single crossover

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...