一个简单的入门尝试
数据的获取
以同花顺软件为例,进入上证指数或者你选择的个股页面,在分时走势这一列切换到日走势(这决定了之后获取的数据时间间隔):
然后按 F1 进入如下界面(按 F3 可切回走势页面):
记录了每日的开盘收盘价、最高最低价、涨跌振幅以及总手数和成交金额,右键导出输出数据选择路径即可。自动保存的格式为.xls,但实际上是.csv,所以会跳出格式与文件后缀不符合,可以先以.xls打开检查一下如上图即正常。
那么有了数据可以先试着自己简单可视化一下,采用 mplfinance
库可以简单绘制K线图:
import pandas as pd
import mplfinance as mpf
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontProperties
# 设置中文字体
font = FontProperties(fname='C:/Windows/Fonts/simsun.ttc')
# 读取csv文件
file_path = 'data/000001.csv'
df = pd.read_csv(file_path, encoding='gbk', sep='\t')
# 去除列名中的空格
df.columns = df.columns.str.strip()
# 提取日期信息并去除星期信息
df['日期'] = df['时间'].str.split(',').str[0]
# 将日期列转换为日期格式
df['日期'] = pd.to_datetime(df['日期'], format='%Y-%m-%d')
# 设置日期为索引
df.set_index('日期', inplace=True)
# 重命名列以符合mplfinance的要求
df.rename(columns={'收盘': 'Close', '最高': 'High', '最低': 'Low', '开盘': 'Open', '总手(万)': 'Volume'}, inplace=True)
# 筛选并打印从2024年开始的数据
df_2024 = df[df.index >= '2024-01-01']
# 自定义样式
mc = mpf.make_marketcolors(up='red', down='green', edge='i', wick='i', volume='in', inherit=True)
s = mpf.make_mpf_style(marketcolors=mc, gridstyle='-', gridcolor='gray', facecolor='lightgray')
# 绘制K线图和成交量
fig, axes = plt.subplots(3, 1, sharex=True, gridspec_kw={'height_ratios': [3, 1, 1]})
mpf.plot(df_2024, type='candle', style=s, ax=axes[0], volume=axes[1], show_nontrading=False)
# 设置标题和标签的字体
axes[0].set_title('K线图', fontproperties=font)
axes[0].set_ylabel('价格', fontproperties=font)
axes[1].set_ylabel('成交量', fontproperties=font)
axes[1].set_xlabel('日期', fontproperties=font)
axes[0].grid(True)
axes[1].grid(True)
plt.show()
以2024年1月1日开始的数据绘制,效果如下:
接着可以试着加入简单计算移动平均线(MA)、相对强弱指数(RSI)和布林带(Bollinger Bands)并打印在图标中。
移动平均线(MA)
移动平均线(Moving Average, MA)是一种技术分析工具,用于平滑价格数据,以便更容易识别价格趋势。它通过计算特定时间段内价格的平均值来实现这一点。常见的移动平均线包括简单移动平均线(SMA)和指数移动平均线(EMA)。
简单移动平均线(SMA):计算特定时间段内价格的算术平均值。例如,20日简单移动平均线(MA20)是过去20天收盘价的平均值。
加权移动平均线(WMA):对最近的价格数据赋予更高的权重,权重按线性降低。
指数移动平均线(EMA):对最近的价格数据赋予更高的权重,权重按指数降低。
通常所说的五日均线(M5)、十日均线(M10)等等就是指五日、十日的简单移动均线。
# 计算移动平均线
df_2024['MA20'] = df_2024['Close'].rolling(window=20).mean()
简单的移动平均线有时过于简单,当价格出现剧烈波动时效果不佳。加权移动平均线则赋予最近时期更多的权重。
故权重通常是一个递增的序列。例如,对于一个窗口大小为 n
的WMA,权重可以是 1, 2, 3, ..., n
计算加权和:将每个数据点乘以其对应的权重,然后求和。
计算权重总和:将所有权重相加。
计算加权平均:将加权和除以权重总和,得到加权移动平均值。
# 计算加权移动平均线(WMA)
def weighted_moving_average(values, window):
weights = np.arange(1, window + 1)
return np.convolve(values, weights[::-1], 'valid') / weights.sum()
df_2024['WMA20'] = np.nan
df_2024['WMA20'].iloc[19:] = weighted_moving_average(df_2024['Close'], 20)
np.convolve(a, v, mode='full')
a
:第一个输入数组。v
:第二个输入数组(通常是权重数组)。mode
:指定卷积的模式,可以是以下值之一:'full'
:返回完整的卷积结果,长度为len(a) + len(v) - 1
。'valid'
:返回有效的卷积结果,长度为len(a) - len(v) + 1
。'same'
:返回与输入数组a
长度相同的卷积结果。
weights[::-1]
是一种使用切片操作来反转数组的方式。
假设有一个权重数组 weights
,其值为 [1, 2, 3]
。反转这个数组后,你会得到 [3, 2, 1]
。这样,当你使用 np.convolve 进行卷积操作时,最近的数据点会乘以最大的权重,而最早的数据点会乘以最小的权重。
EMA的计算公式如下:
其中:
\text{EMA}_t 是当前时刻的EMA值。
P_t 是当前时刻的价格。
\alpha 是平滑系数,通常计算为 \displaystyle\alpha = \frac{2}{N+1},其中 N 是时间窗口大小。
# 计算指数移动平均线(EMA)
def exponential_moving_average(values, window):
alpha = 2 / (window + 1)
ema = [values[0]] # 初始值为第一个价格
for price in values[1:]:
ema.append(alpha * price + (1 - alpha) * ema[-1])
return np.array(ema)
df_2024['EMA20'] = exponential_moving_average(df_2024['Close'], 20)
以今年十月的大涨就可以看出简单20日均线(蓝色)和加权20日均线(橙色)以及指数20日均线(紫色)的对于价格剧烈变化的效果区别:
相对强弱指数(RSI)
相对强弱指数(Relative Strength Index, RSI)是一种动量振荡指标,用于衡量价格变动的速度和变化。RSI的值在0到100之间波动,通常用来识别超买或超卖的市场条件。
计算方法:RSI通常基于14个交易日的价格数据计算。公式如下:
RSI = 100 - \left( \frac{100}{1 + RS} \right)其中,RS(相对强弱)是平均上涨幅度与平均下跌幅度的比值:
RS = \frac{\text{平均上涨幅度}}{\text{平均下跌幅度}}RSI值超过70通常被认为是超买(即RS>2.333,上涨幅度大),可能意味着价格即将回调;RSI值低于30通常被认为是超卖(RS<0.426,下跌幅度大),可能意味着价格即将反弹。
# 计算相对强弱指数(RSI)
delta = df_2024['Close'].diff() # 计算价格变化差值
gain = (delta.where(delta > 0, 0)).rolling(window=14).mean() # 上涨量十四天滑动平均
loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean() # 下跌量十四天滑动平均
rs = gain / loss # 计算RS
df_2024['RSI'] = 100 - (100 / (1 + rs)) # 计算 RSI
布林带(Bollinger Bands)
布林带(Bollinger Bands)由约翰·布林格(John Bollinger)发明,用于衡量市场的波动性。布林带由三条线组成:中轨线、上轨线和下轨线。
中轨线:通常是特定时间段的简单移动平均线(SMA)。
上轨线:中轨线加上两倍的标准差。
下轨线:中轨线减去两倍的标准差。
布林带的宽度反映了市场的波动性。当价格接近上轨线时,市场可能处于超买状态;当价格接近下轨线时,市场可能处于超卖状态。
# 计算布林带
df_2024['BB_Middle'] = df_2024['Close'].rolling(window=20).mean()
df_2024['BB_Upper'] = df_2024['BB_Middle'] + 2 * df_2024['Close'].rolling(window=20).std()
df_2024['BB_Lower'] = df_2024['BB_Middle'] - 2 * df_2024['Close'].rolling(window=20).std()
同时绘制到一张图表: