做套:惊呆了!探究如果机器用KDJ法对股票进行做套的胜率,竟高达%80。
前言:
接上一篇:惊呆了,探究如果机器用MACD法对股票进行做套的胜率,竟高达%80
今天在整理自研量化系统的代码屎山时,也无意间想记录一下如果仅仅严格按照KDJ法对买入的股票进行做套,胜率将会是多少呢?
接下来就来尝试一下,首先得简单了解一下什么是KDJ,这个我也不多解释了,“dddd”,所以简单百度百科一下:随机指标KDJ一般是用于股票分析的统计体系,根据统计学原理,通过一个特定的周期(常为9日、9周等)内出现过的最高价、最低价及最后一个计算周期的收盘价及这三者之间的比例关系,来计算最后一个计算周期的未成熟随机值RSV,然后根据平滑移动平均线的方法来计算K值、D值与J值,并绘成曲线图来研判股票走势。
简单了解完之后就可以开始实现了:
-
第一步导入数据: df = pd.read_csv("2021-11-19.csv")
这里用一下2021年11月19号的上证A股所有股票的日分钟数据 忽略’code’列股票代码显示不全的问题,从数据库备份转csv时没注意code特征列数值的属性,但对这次实验不造成影响,后期把“0”补回去就好了,就是csv保存时把前面的“0”都去掉了,数据量有54w条,足够大了。 -
构造计算KDJ的函数 这里就需要用到kdj的公式了
完整的计算kdj函数的代码为: def CalculateKDJ(price_list, _kdj):
"""
:param price_list:
:param _kdj: 列表 例如 [0, 0, 0]
:return:
"""
RSV = 0
if max(price_list) - min(price_list) != 0:
RSV = (price_list[-1] - min(price_list)) / (max(price_list) - min(price_list)) * 100
K = 2 / 3 * _kdj[0] + 1 / 3 * RSV
D = 2 / 3 * _kdj[1] + 1 / 3 * K
J = 3 * K - 2 * D
return [round(K, 2), round(D, 2), round(J, 2)]
-
此外,还利用sklearn的线性模型库linear_model构造一个可以计算一段时间内价格变动趋势的函数,其实就是分析线性方程组的斜率,从而得知在这段时间,价格变动的趋势 def CalculateTrend(price_list):
"""
:param price_list:
:return:
"""
regr = linear_model.LinearRegression()
X = list()
for x in range(1, len(price_list) + 1):
X.append([x])
regr.fit(X, price_list)
return regr.coef_.tolist()[0]
-
重头戏来了,函数都备好了,万事俱备只欠东风,得构造一个逻辑函数或称为步骤函数去利用数据然后作出决策,然后再判断决策是否正确
然后我叠加了一个用于判断趋势的函数:
-
当判断到买时趋势是向下的(<0),则放弃购买 -
当判断到卖时趋势是向上的(>0),则放弃售卖 判断胜负的方式用,买入(卖出)时的价格低于(高于)接下来10分钟的平均价,则判为胜。 for code in tqdm(set(df['code'].to_list())):
price_list = df[df['code'] == code]['最新价'].to_list()
r = 0
t = 0
threshold = price_list[0]
_KDJ = [50, 50, 0]
for i in range(5, len(price_list), 5):
KDJ = CalculateKDJ(price_list[i - 5:i], _kdj=_KDJ)
if price_list[i] < threshold:
if KDJ[2] >= 100:
if CalculateTrend(price_list[i - 5:i]) > 0:
buy['code'].append(code)
buy['买入价'].append(price_list[i])
buy['买入后十分钟平均价:'].append(np.mean(price_list[i + 1:i + 11]))
r += 1 if price_list[i] <= np.mean(price_list[i + 1:i + 11]) else -1
t += 1
if price_list[i] > threshold:
if KDJ[2] <= 0:
if CalculateTrend(price_list[i - 5:i]) < 0:
sell['code'].append(code)
sell['卖出价'].append(price_list[i])
sell['卖出后十分钟平均价:'].append(np.mean(price_list[i + 1:i + 11]))
r += 1 if price_list[i] >= np.mean(price_list[i + 1:i + 11]) else -1
t += 1
_KDJ = KDJ
if t != 0:
rate['code'].append(code)
rate['胜率'].append(r / t)
一通捣鼓下来,观看实验效果:
-
仅用“J指标取值超过100和低于0,都属于价格的非正常区域,大于100为超买,小0为超卖。” 胜率为 -
用“J指标取值超过100和低于0,都属于价格的非正常区域,大于100为超买,小0为超卖。”和 D大于80时,行情呈现超买现象。D小于20时,行情呈现超卖现象。“胜率为 ,反而降低了 -
用“当K值由较小逐渐大于D值,在图形上显示K线从下方上穿D线,所以在图形上K线向上突破D线时,俗称金叉,即为买进的讯号”和“当K值由较大逐渐小于D值,在图形上显示K线从上方下穿D线,所以在图形上K线向下突破D线时,俗称死叉,即为卖出的讯号”胜率为 可见J值更敏感,对于这种“日内做套”的手段,胜率显得更高一点。
完整代码:
import pandas as pd
from sklearn import linear_model
from tqdm import tqdm
import numpy as np
def CalculateKDJ(price_list, _kdj):
"""
:param price_list:
:param _kdj: 列表 例如 [0, 0, 0]
:return:
"""
RSV = 0
if max(price_list) - min(price_list) != 0:
RSV = (price_list[-1] - min(price_list)) / (max(price_list) - min(price_list)) * 100
K = 2 / 3 * _kdj[0] + 1 / 3 * RSV
D = 2 / 3 * _kdj[1] + 1 / 3 * K
J = 3 * K - 2 * D
return [round(K, 2), round(D, 2), round(J, 2)]
def CalculateTrend(price_list):
"""
:param price_list:
:return:
"""
regr = linear_model.LinearRegression()
X = list()
for x in range(1, len(price_list) + 1):
X.append([x])
regr.fit(X, price_list)
return regr.coef_.tolist()[0]
if __name__ == '__main__':
df = pd.read_csv("min_test_data.csv")
buy = {'code': list(), '买入价': list(), '买入后十分钟平均价:': list()}
sell = {'code': list(), '卖出价': list(), '卖出后十分钟平均价:': list()}
rate = {'code': list(), '胜率': list()}
for code in tqdm(set(df['code'].to_list())):
price_list = df[df['code'] == code]['最新价'].to_list()
r = 0
t = 0
threshold = price_list[0]
_KDJ = [50, 50, 0]
for i in range(5, len(price_list), 5):
KDJ = CalculateKDJ(price_list[i - 5:i], _kdj=_KDJ)
if price_list[i] < threshold:
if KDJ[2] >= 100:
if CalculateTrend(price_list[i - 5:i]) > 0:
buy['code'].append(code)
buy['买入价'].append(price_list[i])
buy['买入后十分钟平均价:'].append(np.mean(price_list[i + 1:i + 11]))
r += 1 if price_list[i] <= np.mean(price_list[i + 1:i + 11]) else -1
t += 1
if price_list[i] > threshold:
if KDJ[2] <= 0:
if CalculateTrend(price_list[i - 5:i]) < 0:
sell['code'].append(code)
sell['卖出价'].append(price_list[i])
sell['卖出后十分钟平均价:'].append(np.mean(price_list[i + 1:i + 11]))
r += 1 if price_list[i] >= np.mean(price_list[i + 1:i + 11]) else -1
t += 1
_KDJ = KDJ
if t != 0:
rate['code'].append(code)
rate['胜率'].append(r / t)
buy = pd.DataFrame(buy)
print(buy.head())
sell = pd.DataFrame(sell)
print(sell.head())
rate = pd.DataFrame(rate)
print(rate.head())
print(rate['胜率'].sum() / len(rate))
|