Matplotlib绘制X轴刻度之间的市场图。

huangapple go评论82阅读模式
英文:

Matplotlib plot market between ticks (X axis)

问题

I'm calculating 2 moving averages from a stock price and finding if they crossed over. When they crossover, I want to show in the graph a marker on top of it.

To find the crossovers, I'm using this code:

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

where df_status is a list with -1, 0 and 1 from the two moving averages. The idxs gives me the index position from df_status where the crossover happened.

The problem is when the cross is between 2 dates, as seen in the picture below:
Matplotlib绘制X轴刻度之间的市场图。

How can I move the marker to be centered on the crossover than in the date that it was detected?

Code to reproduce:

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 + 1], df['SMA_100'][marker + 1], marker='o', markersize=35, alpha=.5)
plt.show()

In this code, the crossover is at index 8, but the crossover happens in the graph between indexes 8 and 9. How can I position the marker between the two X ticks?

英文:

I'm calculating 2 moving averages from a stock price and finding if they crossed over. When they crossover, I want to show in the graph a marker on top of it.

To find the crossovers, I'm using this code:

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

where df_status is a list with -1, 0 and 1 from the two moving averages. The idxs gives me the index position from df_status where the crossover happened.

The problem is when the cross is between 2 dates, as seen in the picture below:
Matplotlib绘制X轴刻度之间的市场图。

How can I move the marker to be centered on the crossover than in the date that it was detected?

Code to reproduce:

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()

In this code, the crossover is at index 8, but the crossover happen in the graph between indexes 8 and 9. How can I position the marker between the two X ticks?

答案1

得分: 2

IIUC,要找到交叉点 '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() # 获取交叉点

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()

输出结果:

Matplotlib绘制X轴刻度之间的市场图。

英文:

IIUC, to find crossover 'SMA_10' and 'SMA_100' try this:

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()

Output:

Matplotlib绘制X轴刻度之间的市场图。

答案2

得分: 1

使用 @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'])
# 获取交叉点
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()

Matplotlib绘制X轴刻度之间的市场图。
Matplotlib绘制X轴刻度之间的市场图。

英文:

Using @ScottBoston suggestion, I came up with this solution that works with single and multiple crossovers:

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()

Matplotlib绘制X轴刻度之间的市场图。
Matplotlib绘制X轴刻度之间的市场图。

huangapple
  • 本文由 发表于 2020年1月6日 23:53:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/59615119.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定