python识别股票K线形态,准确率回测(一)

李魔佛 发表了文章 • 0 个评论 • 28 次浏览 • 2022-05-22 01:13 • 来自相关话题

python识别股票K线形态,准确率回测(一)

对于一些做股票技术分析的投资者来说,对常见的k线形态应该都不陌生,比如十字星,红三兵,头肩顶(底),岛型反转,吊颈线,两只乌鸦,三只乌鸦,四只乌鸦(哈)








做价投的投资者可能会对这些划线的嗤之以鼻,而短线操盘者却有可能把它奉为圭臬,以之作为买卖标准。

海乃百川,兼听则明,笔者认为多吸收不同的观点与技术,可以更加全面的加深投资认知。你画的圆圈越大,圆圈外的未知空间也越大。

本文介绍使用python对A股市场的股票(转债也可以)的K线进行识别,然后回测某个形态出现后接下来的涨跌幅,还可以通过设定的形态进行选股。

举个例子,我们可以统计所有个股出现了“早晨之星“这一形态后,一周后甚至一个月后,个股是涨了还是跌了,从大量结果中统计出一些有意义的结果。

为了便于验证查看结果图形,我们先介绍如何使用python来画股票K线图。

有数据之后,剩下画图是很简单的,很多第三方的库已经封装好了各种蜡烛图绘制函数。我们要做只是传入每天开,收盘价,以及最高最低价。

获取股票的数据

市面有不少第三方的库可以获取股票和可转债的日线数据,比如tushare和akshare。本文以股票数据为例。

以akshare为例,代码如下所示:
 
# pip install akshare
import akshare as ak
def get_k_line(code="sz002241"): #
df = ak.stock_zh_a_daily(symbol=code, start_date="20220101", end_date="20220515",
adjust="qfq")
# 这个函数只适合取股票数据,转债会报错,转债的日线数据可以使用其他函数,这里选择股价前复权
df.to_excel("同和药业k.xlsx")
如上面代码所示,我们使用stock_zh_a_daily方法获取一段时间的数据,这里的日期可以根据你的需求进行调整,比如设置start_date=“20200101”,end_date=“20220515”,就可以获取一年时间段的股票数据。

而股票的代码有sh与sz之分,sz代表深市的股票,所有深市的股票前面都必须带上sz,比如这里的同和药业,就是sz002241。

同样的,sh是上证交易所的股票,所有上证的股票前面必须带上sh。

这里,我们来看看获取的同和药业股票数据格式,如下图所示:

date:交易日期
open:代表开盘价
high:当天最高价
low:当天最低价
close:当天收盘价
volume:当天成交量(元)
outstanding_share:流动股本(股)
turnover:换手率

既然已经拿到了数据,下面我们来绘制K线图。

绘制K线图

在python中,绘制K线图需要用到mpl_finance库,而这个库提供了4种方式绘制K线图,这里我们介绍其中的一种,代码如下所示:
 
import mpl_finance as mpf
import matplotlib.pyplot as plt
import pandas as pd

#创建绘图的基本参数
fig=plt.figure(figsize=(12, 8))
ax=fig.add_subplot(111)

#获取刚才的股票数据
df = pd.read_excel("同和药业k.xlsx")
mpf.candlestick2_ochl(ax, df["open"], df["close"], df["high"], df["low"], width=0.6, colorup='r',colordown='green',alpha=1.0)
#显示出来
plt.show()
运行此段代码后,会显示如下效果图:






和东财上的同和药业的k线图基本一致的。

不过,这个K线图有一个问题,就是X坐标轴并不是显示的时间,而是数字,这是因为我们绘制K线图的方法,并没有提供X轴的参数,那怎么让下面的数字替换为时间呢?
 
我们先来看一段代码:
import matplotlib.ticker as ticker
#将股票时间转换为标准时间,不带时分秒的数据
def date_to_num(dates):
num_time = []
for date in dates:
date_time = datetime.strptime(date, '%Y-%m-%d')
num_date = date2num(date_time)
num_time.append(num_date)
return num_time

#创建绘图的基本参数
fig=plt.figure(figsize=(12, 8))
ax=fig.add_subplot(111)

#获取刚才的股票数据
df = pd.read_excel("同和药业k.xlsx")
mpf.candlestick2_ochl(ax, df["open"], df["close"], df["high"], df["low"], width=0.6, colorup='r',colordown='green',alpha=1.0)
df['date'] = pd.to_datetime(df['date'])
df['date'] = df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
def format_date(x, pos=None):
if x < 0 or x > len(df['date']) - 1:
return ''
return df['date'][int(x)]
ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
#显示出来
plt.show()
 
这里,我们定义了2个方法:第1个方法date_to_num主要的作用就是将获取的时间数据转换为标准的日期数据;第2个方法,就是根据X的数值替换时间值。

其中,set_major_formatter方法是将数值替换为时间值的操作库,而plt.setup的功能就是设置X轴的标签倾斜45度以及右对齐。运行之后,我们的K线图就显示的非常完美了,如下图所示:



均线图

虽然我们实现了K线图,但是有没有发现,其实大多数的股票交易软件K线图上面其实还标记有均线,比如常用的有5日均线,10日均线,30均线。
所以,我们需要将均线一起添加到我们的K线图之上。
计算均线的方式如下:
df["SMA5"] = df["close"].rolling(5).mean()
df["SMA10"] = df["close"].rolling(10).mean()
df["SMA30"] = df["close"].rolling(30).mean()
 
3行代码就可以获取到股票的均线值。
接着,我们可以使用上面的ax进行绘制均线了,
添加的代码如下所示:
 
ax.plot(np.arange(0, len(df)), df['SMA5']) # 绘制5日均线
ax.plot(np.arange(0, len(df)), df['SMA10']) # 绘制10日均线
ax.plot(np.arange(0, len(df)), df['SMA30']) # 绘制30日均线
这里,同样将X轴设置为数字,将这两段代码添加到上面的K线图代码中,自然也会将X轴替换为时间。运行之后,显示效果如下图所示:


 
这里5日均线为蓝色,10日均线为橙色,30日均线为绿色,如果需要自己设置颜色,可以在每条均线的的绘制方法中加入color参数。


细心的读者肯定发现30日均线只有最后一小段,这是因为前29日不够30日是算不出均线的,同样的5,10日均线也是如此。

成交量

最后,我们还需要绘制成交量。在多数的股票交易软件中,上面是K线图,一般下面对应的就是成交量,这样对比起来看,往往能直观的看到数据的变化。

但是,因为上面有个K线图,那么同一个画布中就有了2个图片,且它们共用一个X轴,那么我们需要更改一下基本的参数,
 
代码如下所示:
import mpl_finance as mpf
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.ticker as ticker
import numpy as np
#创建绘图的基本参数
fig, axes = plt.subplots(2, 1, sharex=True, figsize=(15, 10))
ax1, ax2 = axes.flatten()

#获取刚才的股票数据
df = pd.read_excel("同和药业k.xlsx")
mpf.candlestick2_ochl(ax1, df["open"], df["close"], df["high"], df["low"], width=0.6, colorup='r',colordown='green',alpha=1.0)
df['date'] = pd.to_datetime(df['date'])
df['date'] = df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
def format_date(x, pos=None):
if x < 0 or x > len(df['date']) - 1:
return ''
return df['date'][int(x)]
df["SMA5"] = df["close"].rolling(5).mean()
df["SMA10"] = df["close"].rolling(10).mean()
df["SMA30"] = df["close"].rolling(30).mean()
ax1.plot(np.arange(0, len(df)), df['SMA5']) # 绘制5日均线
ax1.plot(np.arange(0, len(df)), df['SMA10']) # 绘制10日均线
ax1.plot(np.arange(0, len(df)), df['SMA30']) # 绘制30日均线
ax1.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
#显示出来
plt.show()
 
这里,我们将绘图的画布设置为2行1列。同时,将上面绘制的所有数据都更改为ax1,这样均线与K线图会绘制到第一个子图中。

接着,我们需要绘制成交量,但是我们知道,一般股票交易软件都将上涨的那天成交量设置为红色,而将下跌的成交量绘制成绿色。所以,首先我们要做的是将获取的股票数据根据当天的涨跌情况进行分类。
 
具体代码如下:
 
red_pred = np.where(df["close"] > df["open"], df["volume"], 0)
blue_pred = np.where(df["close"] < df["open"], df["volume"], 0)
 
如上面代码所示,我们通过np.where(condition, x, y)筛选数据。这里满足条件condition,输出X,不满足条件输出Y,这样我们就将涨跌的成交量数据进行了分类。

最后,我们直接通过柱状图方法绘制成交量,
具体代码如下所示:
ax2.bar(np.arange(0, len(df)), red_pred, facecolor="red")
ax2.bar(np.arange(0, len(df)), blue_pred, facecolor="blue")
 
将这4行代码,全部加入到plt.show()代码的前面即可。

运行之后,输出的效果图如下:


根据定义编写形态

接下来,我们根据定义来构造一个简单的形态函数,比如长上影线。

上影线


根据网络上的定义:

⑤上影阳线:开盘后价格冲高回落,涨势受阻,虽然收盘价仍高于开盘价,但上方有阻力,可视为弱势。

⑥上影阴线:开盘后价格冲高受阻,涨势受阻,收盘价低于开盘价,上方有阻力,可视为弱势。








那么简单定义为:(high - close)/close > 7%,(high - open)/open > 7% ,可能不是太精确,这里只是为了演示,忽略一些具体细节。

简单理解就是,当天最高价比收盘价,开盘价高得多。

长上影匹配函数,简单,只有一行就搞定。
 
def long_up_shadow(o,c,h,l):
return True if (h-c)/c >=0.07 and (h-o)/o>=0.07 else False
 
 
然后把这个长上影函数应用到上面的同和药业。
 
得到的效果:
df = pd.read_excel("同和药业k.xlsx")
count_num = []
for row,item in df.iterrows():
if long_up_shadow(item['open'],item['close'],item['high'],item['low']):
count_num.append(row)

plot_image(df,count_num)
 
图里面的4个箭头长上影是python自动标上去的,然后对着数据到同花顺核对一下,都是满足长度大于7%的。

可以看到在3月18日和28日的两根长上影之后,同和药业的股价走了一波趋势下跌。【PS:选这个股票并没有刻意去挑选,在集思录默认排名,找了一个跌幅第一个转债的正股就把代码拷贝过来测试】

那么,有这么多的形态,难道每一个都要自己写代码筛选形态吗? 不用哈,因为已经有人写了第三方的库,你只需要调用就可以了。


截取的部分函数名与说明


比如,像两只乌鸦,描述起来都感觉有点复杂,自己手撸代码都会搞出一堆bug。而用taLib这个库,你只需要一行调用代码,就可以完成这些复杂的形态筛选工作。

示例代码:
df['tow_crows'] = talib.CDL2CROWS(df['open'].values, df['high'].values, df['low'].values, df['close'].values)

pattern = df[(df['tow_crows'] == 100) | (df['tow_crows'] == -100)]
 
 
上面得到的pattern就是满足要求的形态,如CDL2CROWS 两只乌鸦。测试的个股是歌尔股份2020的日K线。

虽然我不知道两只乌鸦是什么玩意,但是可以通过遍历某个长周期(5-10年)下的全部A股数据,通过数据证伪,统计这个形态过后的一周或一个月(个人随意设定)涨跌幅,来证伪这个形态的有效性。

如果得到的是一个50%概率涨跌概况,那说明这个指标形态只是个游走在随机概率的指标,并不能作为一个有效指标参考。

(未完待续) 查看全部
python识别股票K线形态,准确率回测(一)

对于一些做股票技术分析的投资者来说,对常见的k线形态应该都不陌生,比如十字星,红三兵,头肩顶(底),岛型反转,吊颈线,两只乌鸦,三只乌鸦,四只乌鸦(哈)


faedab64034f78f02380501cf58b9d5cb1191c9e.jpeg



做价投的投资者可能会对这些划线的嗤之以鼻,而短线操盘者却有可能把它奉为圭臬,以之作为买卖标准。

海乃百川,兼听则明,笔者认为多吸收不同的观点与技术,可以更加全面的加深投资认知。你画的圆圈越大,圆圈外的未知空间也越大。

本文介绍使用python对A股市场的股票(转债也可以)的K线进行识别,然后回测某个形态出现后接下来的涨跌幅,还可以通过设定的形态进行选股。

举个例子,我们可以统计所有个股出现了“早晨之星“这一形态后,一周后甚至一个月后,个股是涨了还是跌了,从大量结果中统计出一些有意义的结果。

为了便于验证查看结果图形,我们先介绍如何使用python来画股票K线图。

有数据之后,剩下画图是很简单的,很多第三方的库已经封装好了各种蜡烛图绘制函数。我们要做只是传入每天开,收盘价,以及最高最低价。

获取股票的数据

市面有不少第三方的库可以获取股票和可转债的日线数据,比如tushare和akshare。本文以股票数据为例。

以akshare为例,代码如下所示:
 
# pip install akshare 
import akshare as ak
def get_k_line(code="sz002241"): #
df = ak.stock_zh_a_daily(symbol=code, start_date="20220101", end_date="20220515",
adjust="qfq")
# 这个函数只适合取股票数据,转债会报错,转债的日线数据可以使用其他函数,这里选择股价前复权
df.to_excel("同和药业k.xlsx")

如上面代码所示,我们使用stock_zh_a_daily方法获取一段时间的数据,这里的日期可以根据你的需求进行调整,比如设置start_date=“20200101”,end_date=“20220515”,就可以获取一年时间段的股票数据。

而股票的代码有sh与sz之分,sz代表深市的股票,所有深市的股票前面都必须带上sz,比如这里的同和药业,就是sz002241。

同样的,sh是上证交易所的股票,所有上证的股票前面必须带上sh。

这里,我们来看看获取的同和药业股票数据格式,如下图所示:

date:交易日期
open:代表开盘价
high:当天最高价
low:当天最低价
close:当天收盘价
volume:当天成交量(元)
outstanding_share:流动股本(股)
turnover:换手率


既然已经拿到了数据,下面我们来绘制K线图。

绘制K线图

在python中,绘制K线图需要用到mpl_finance库,而这个库提供了4种方式绘制K线图,这里我们介绍其中的一种,代码如下所示:
 
import mpl_finance as mpf
import matplotlib.pyplot as plt
import pandas as pd

#创建绘图的基本参数
fig=plt.figure(figsize=(12, 8))
ax=fig.add_subplot(111)

#获取刚才的股票数据
df = pd.read_excel("同和药业k.xlsx")
mpf.candlestick2_ochl(ax, df["open"], df["close"], df["high"], df["low"], width=0.6, colorup='r',colordown='green',alpha=1.0)
#显示出来
plt.show()

运行此段代码后,会显示如下效果图:






和东财上的同和药业的k线图基本一致的。

不过,这个K线图有一个问题,就是X坐标轴并不是显示的时间,而是数字,这是因为我们绘制K线图的方法,并没有提供X轴的参数,那怎么让下面的数字替换为时间呢?
 
我们先来看一段代码:
import matplotlib.ticker as ticker
#将股票时间转换为标准时间,不带时分秒的数据
def date_to_num(dates):
num_time = []
for date in dates:
date_time = datetime.strptime(date, '%Y-%m-%d')
num_date = date2num(date_time)
num_time.append(num_date)
return num_time

#创建绘图的基本参数
fig=plt.figure(figsize=(12, 8))
ax=fig.add_subplot(111)

#获取刚才的股票数据
df = pd.read_excel("同和药业k.xlsx")
mpf.candlestick2_ochl(ax, df["open"], df["close"], df["high"], df["low"], width=0.6, colorup='r',colordown='green',alpha=1.0)
df['date'] = pd.to_datetime(df['date'])
df['date'] = df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
def format_date(x, pos=None):
if x < 0 or x > len(df['date']) - 1:
return ''
return df['date'][int(x)]
ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
#显示出来
plt.show()

 
这里,我们定义了2个方法:第1个方法date_to_num主要的作用就是将获取的时间数据转换为标准的日期数据;第2个方法,就是根据X的数值替换时间值。

其中,set_major_formatter方法是将数值替换为时间值的操作库,而plt.setup的功能就是设置X轴的标签倾斜45度以及右对齐。运行之后,我们的K线图就显示的非常完美了,如下图所示:



均线图

虽然我们实现了K线图,但是有没有发现,其实大多数的股票交易软件K线图上面其实还标记有均线,比如常用的有5日均线,10日均线,30均线。
所以,我们需要将均线一起添加到我们的K线图之上。
计算均线的方式如下:
df["SMA5"] = df["close"].rolling(5).mean()
df["SMA10"] = df["close"].rolling(10).mean()
df["SMA30"] = df["close"].rolling(30).mean()

 
3行代码就可以获取到股票的均线值。
接着,我们可以使用上面的ax进行绘制均线了,
添加的代码如下所示:
 
ax.plot(np.arange(0, len(df)), df['SMA5'])  # 绘制5日均线
ax.plot(np.arange(0, len(df)), df['SMA10']) # 绘制10日均线
ax.plot(np.arange(0, len(df)), df['SMA30']) # 绘制30日均线

这里,同样将X轴设置为数字,将这两段代码添加到上面的K线图代码中,自然也会将X轴替换为时间。运行之后,显示效果如下图所示:


 
这里5日均线为蓝色,10日均线为橙色,30日均线为绿色,如果需要自己设置颜色,可以在每条均线的的绘制方法中加入color参数。


细心的读者肯定发现30日均线只有最后一小段,这是因为前29日不够30日是算不出均线的,同样的5,10日均线也是如此。

成交量

最后,我们还需要绘制成交量。在多数的股票交易软件中,上面是K线图,一般下面对应的就是成交量,这样对比起来看,往往能直观的看到数据的变化。

但是,因为上面有个K线图,那么同一个画布中就有了2个图片,且它们共用一个X轴,那么我们需要更改一下基本的参数,
 
代码如下所示:
import mpl_finance as mpf
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.ticker as ticker
import numpy as np
#创建绘图的基本参数
fig, axes = plt.subplots(2, 1, sharex=True, figsize=(15, 10))
ax1, ax2 = axes.flatten()

#获取刚才的股票数据
df = pd.read_excel("同和药业k.xlsx")
mpf.candlestick2_ochl(ax1, df["open"], df["close"], df["high"], df["low"], width=0.6, colorup='r',colordown='green',alpha=1.0)
df['date'] = pd.to_datetime(df['date'])
df['date'] = df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
def format_date(x, pos=None):
if x < 0 or x > len(df['date']) - 1:
return ''
return df['date'][int(x)]
df["SMA5"] = df["close"].rolling(5).mean()
df["SMA10"] = df["close"].rolling(10).mean()
df["SMA30"] = df["close"].rolling(30).mean()
ax1.plot(np.arange(0, len(df)), df['SMA5']) # 绘制5日均线
ax1.plot(np.arange(0, len(df)), df['SMA10']) # 绘制10日均线
ax1.plot(np.arange(0, len(df)), df['SMA30']) # 绘制30日均线
ax1.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
#显示出来
plt.show()

 
这里,我们将绘图的画布设置为2行1列。同时,将上面绘制的所有数据都更改为ax1,这样均线与K线图会绘制到第一个子图中。

接着,我们需要绘制成交量,但是我们知道,一般股票交易软件都将上涨的那天成交量设置为红色,而将下跌的成交量绘制成绿色。所以,首先我们要做的是将获取的股票数据根据当天的涨跌情况进行分类。
 
具体代码如下:
 
red_pred = np.where(df["close"] > df["open"], df["volume"], 0)
blue_pred = np.where(df["close"] < df["open"], df["volume"], 0)

 
如上面代码所示,我们通过np.where(condition, x, y)筛选数据。这里满足条件condition,输出X,不满足条件输出Y,这样我们就将涨跌的成交量数据进行了分类。

最后,我们直接通过柱状图方法绘制成交量,
具体代码如下所示:
ax2.bar(np.arange(0, len(df)), red_pred, facecolor="red")
ax2.bar(np.arange(0, len(df)), blue_pred, facecolor="blue")

 
将这4行代码,全部加入到plt.show()代码的前面即可。

运行之后,输出的效果图如下:


根据定义编写形态

接下来,我们根据定义来构造一个简单的形态函数,比如长上影线。

上影线


根据网络上的定义:

⑤上影阳线:开盘后价格冲高回落,涨势受阻,虽然收盘价仍高于开盘价,但上方有阻力,可视为弱势。

⑥上影阴线:开盘后价格冲高受阻,涨势受阻,收盘价低于开盘价,上方有阻力,可视为弱势。


a63d1fc08915cbf8f22f333a3226f331.jpeg



那么简单定义为:(high - close)/close > 7%,(high - open)/open > 7% ,可能不是太精确,这里只是为了演示,忽略一些具体细节。

简单理解就是,当天最高价比收盘价,开盘价高得多。

长上影匹配函数,简单,只有一行就搞定。
 
def long_up_shadow(o,c,h,l):
return True if (h-c)/c >=0.07 and (h-o)/o>=0.07 else False

 
 
然后把这个长上影函数应用到上面的同和药业。
 
得到的效果:
df = pd.read_excel("同和药业k.xlsx")
count_num = []
for row,item in df.iterrows():
if long_up_shadow(item['open'],item['close'],item['high'],item['low']):
count_num.append(row)

plot_image(df,count_num)

 
图里面的4个箭头长上影是python自动标上去的,然后对着数据到同花顺核对一下,都是满足长度大于7%的。

可以看到在3月18日和28日的两根长上影之后,同和药业的股价走了一波趋势下跌。【PS:选这个股票并没有刻意去挑选,在集思录默认排名,找了一个跌幅第一个转债的正股就把代码拷贝过来测试】

那么,有这么多的形态,难道每一个都要自己写代码筛选形态吗? 不用哈,因为已经有人写了第三方的库,你只需要调用就可以了。


截取的部分函数名与说明


比如,像两只乌鸦,描述起来都感觉有点复杂,自己手撸代码都会搞出一堆bug。而用taLib这个库,你只需要一行调用代码,就可以完成这些复杂的形态筛选工作。

示例代码:
df['tow_crows'] = talib.CDL2CROWS(df['open'].values, df['high'].values, df['low'].values, df['close'].values)

pattern = df[(df['tow_crows'] == 100) | (df['tow_crows'] == -100)]

 
 
上面得到的pattern就是满足要求的形态,如CDL2CROWS 两只乌鸦。测试的个股是歌尔股份2020的日K线。

虽然我不知道两只乌鸦是什么玩意,但是可以通过遍历某个长周期(5-10年)下的全部A股数据,通过数据证伪,统计这个形态过后的一周或一个月(个人随意设定)涨跌幅,来证伪这个形态的有效性。

如果得到的是一个50%概率涨跌概况,那说明这个指标形态只是个游走在随机概率的指标,并不能作为一个有效指标参考。

(未完待续)

QMT非常吃内存,且千万不要断网运行

李魔佛 发表了文章 • 0 个评论 • 301 次浏览 • 2022-03-21 23:47 • 来自相关话题

一台I7的笔记本,本身CPU风扇是静音不转的,打开QMT后就开始猛转。
 
而在网络状况极差或者断网的情况下,会有个bug,就是可以把机子的内存吃满。笔记本配的24GB的内存,然鹅。。。。
 
还是卡死了。 连任务管理器都打不开。经常漫长的等待,最后还是按下了重启按钮(硬重启)。
 






 
  查看全部
一台I7的笔记本,本身CPU风扇是静音不转的,打开QMT后就开始猛转。
 
而在网络状况极差或者断网的情况下,会有个bug,就是可以把机子的内存吃满。笔记本配的24GB的内存,然鹅。。。。
 
还是卡死了。 连任务管理器都打不开。经常漫长的等待,最后还是按下了重启按钮(硬重启)。
 

20220507234742524.png


 
 

迅投QMT实时调用集思录数据 自动交易教程

李魔佛 发表了文章 • 0 个评论 • 632 次浏览 • 2022-03-20 19:13 • 来自相关话题

在QMT自带的文档里面,实在找不到任何的溢价率的数据,连转股价也没有,只有光秃秃的一个价格。所以在可转债多因子量化交易里面实在无法进行下去。

不过好在QMT支持第三方库,并且也可以连通外部数据,不像Ptrade那样封闭(Ptrade里面os这个内置库都被阉割了,更别说访问外部数据),所以笔者就写了一个实时访问集思录数据的接口,供QMT访问。

使用flask做接口是最简单,可是flask性能非常低下,故使用异步框架uvicorn +asgi。
 

 
返回了383个转债数据,只要集思录上有的,都可以获取到QMT里面。

在QMT里面的调用函数就8行:

 
其主要核心是之前的文章里面登录并获取集思录数据。然后套一个web接口调用即可。

而这里也把之前集思录密码加密部分改为自己使用AES加密,省去了JS执行的流程,简化了运行流程,提升了效率。

 
每次请求大约需要0.8~0.9秒左右。

 
运行方式:

先把依赖安装好, pip install -r requirements.txt

然后 python app.py

就在后台运行了,不要关闭。

然后用浏览器打开 http://127.0.0.1:8080 如果有数据就说明成功了。

QMT部分的代码:
def get_jisilu_data():
try:
r = requests.get('http://127.0.0.1:8080/jisilu')
except Exception as e:
print(e)
return []
else:
return r.json()
 
调用上面本地的接口就可以获取数据了。

PS:提升速度TIP

第一次运行的时候 cache=False





 
会保存你的用户名密码加密数据,然后后续可以关闭上面的python程序,把上面代码的cache=False改为cache=True, 重新运行,这样速度会得到提升。因为不用每次都做AES计算了,因为每次对用户名密码做AES运算的结果第一次已经保存下来。
 
更多QMT教程,可以关注公众号与知识星球 查看全部
在QMT自带的文档里面,实在找不到任何的溢价率的数据,连转股价也没有,只有光秃秃的一个价格。所以在可转债多因子量化交易里面实在无法进行下去。

不过好在QMT支持第三方库,并且也可以连通外部数据,不像Ptrade那样封闭(Ptrade里面os这个内置库都被阉割了,更别说访问外部数据),所以笔者就写了一个实时访问集思录数据的接口,供QMT访问。

使用flask做接口是最简单,可是flask性能非常低下,故使用异步框架uvicorn +asgi。
 

 
返回了383个转债数据,只要集思录上有的,都可以获取到QMT里面。

在QMT里面的调用函数就8行:

 
其主要核心是之前的文章里面登录并获取集思录数据。然后套一个web接口调用即可。

而这里也把之前集思录密码加密部分改为自己使用AES加密,省去了JS执行的流程,简化了运行流程,提升了效率。

 
每次请求大约需要0.8~0.9秒左右。

 
运行方式:

先把依赖安装好, pip install -r requirements.txt

然后 python app.py

就在后台运行了,不要关闭。

然后用浏览器打开 http://127.0.0.1:8080 如果有数据就说明成功了。

QMT部分的代码:
def get_jisilu_data():
try:
r = requests.get('http://127.0.0.1:8080/jisilu')
except Exception as e:
print(e)
return []
else:
return r.json()

 
调用上面本地的接口就可以获取数据了。

PS:提升速度TIP

第一次运行的时候 cache=False

20220319223129.png

 
会保存你的用户名密码加密数据,然后后续可以关闭上面的python程序,把上面代码的cache=False改为cache=True, 重新运行,这样速度会得到提升。因为不用每次都做AES计算了,因为每次对用户名密码做AES运算的结果第一次已经保存下来。
 
更多QMT教程,可以关注公众号与知识星球

迅投QMT技术交流群

绫波丽 发表了文章 • 0 个评论 • 296 次浏览 • 2022-03-17 15:25 • 来自相关话题

找了一圈,发现网上居然没有这个量化交易的交流群,或者文章。所以只好搞一个群,欢迎志于在QMT量化领域的朋友加入。 
 

 
可以扫码加入:

备注qmt群 查看全部
找了一圈,发现网上居然没有这个量化交易的交流群,或者文章。所以只好搞一个群,欢迎志于在QMT量化领域的朋友加入。 
 

 
可以扫码加入:

备注qmt群

Cannot import name 'StringIO' from 'pandas.compat'

回复

李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 342 次浏览 • 2022-02-11 17:11 • 来自相关话题

Ptrade、QMT如何在虚拟机下运行?

李魔佛 发表了文章 • 0 个评论 • 658 次浏览 • 2022-01-12 19:38 • 来自相关话题

QMT在阿里云的虚拟机上无法运行的,QMT会检测到当前的环境是虚拟机,会阻止你登录。
 
那是不是只能在本地的物理机上执行的呢?
 
不过有办法解决:
使用阿里云的云服务中的无影云。
 
关键它价格也不贵,一年的2核4G的价格也就是139元,支持windows
 

 https://www.aliyun.com/minisite/goods?userCode=nebb965s

无影云桌面 (Elastic Desktop Service),是一种易用、安全、高效的云上桌面服务。它支持快速便捷的桌面环境创建、部署、统一管控与运维。无需前期传统硬件投资,帮您快速构建安全、高性能、低成本的企业桌面办公体系。可广泛应用于具有高数据安全管控、高性能计算等要求的安全办公、金融、设计、影视、教育等领域。

 其实就是一个windows的远程桌面,里面可以按照各种应用程序,比如同花顺,东方财富,QQ等等

 
连接方式,使用浏览器就可以连上远程桌面了:
 

我用的谷歌浏览器,现在无论走到那里,只要可以上网,就可以在浏览器里面连接到远程桌面,看到QMT里面的情况。
 

  查看全部
QMT在阿里云的虚拟机上无法运行的,QMT会检测到当前的环境是虚拟机,会阻止你登录。
 
那是不是只能在本地的物理机上执行的呢?
 
不过有办法解决:
使用阿里云的云服务中的无影云。
 
关键它价格也不贵,一年的2核4G的价格也就是139元,支持windows
 

 https://www.aliyun.com/minisite/goods?userCode=nebb965s


无影云桌面 (Elastic Desktop Service),是一种易用、安全、高效的云上桌面服务。它支持快速便捷的桌面环境创建、部署、统一管控与运维。无需前期传统硬件投资,帮您快速构建安全、高性能、低成本的企业桌面办公体系。可广泛应用于具有高数据安全管控、高性能计算等要求的安全办公、金融、设计、影视、教育等领域。


 其实就是一个windows的远程桌面,里面可以按照各种应用程序,比如同花顺,东方财富,QQ等等

 
连接方式,使用浏览器就可以连上远程桌面了:
 

我用的谷歌浏览器,现在无论走到那里,只要可以上网,就可以在浏览器里面连接到远程桌面,看到QMT里面的情况。
 

 

QMT代码详解<一> 行业ETF轮动

李魔佛 发表了文章 • 0 个评论 • 625 次浏览 • 2021-12-15 17:33 • 来自相关话题

回测代码如下: 代码里面加入了个人理解的注释。
 
#coding:gbk

'''
回测模型示例(非实盘交易策略)

本策略每隔1个月定时触发计算1000能源(399381.SZ)、1000材料(399382.SZ)、1000工业(399383.SZ)、
1000可选(399384.SZ)、1000消费(399385.SZ)、1000医药(399386.SZ)这几个行业指数过去
20个交易日的收益率并选取了收益率最高的指数的成份股并获取了他们的市值数据
随后把仓位调整至市值最大的5只股票上
该策略在股票指数日线下运行
'''
import numpy as np
import math
def init(ContextInfo):
MarketPosition ={}
ContextInfo.MarketPosition = MarketPosition #初始化持仓
index_universe = ['399381.SZ','399382.SZ','399383.SZ','399384.SZ','399385.SZ','399386.SZ']
index_stocks = []
for index in index_universe:
for stock in ContextInfo.get_sector(index): # 获取指数的成分股
index_stocks.append(stock)
ContextInfo.set_universe(index_universe+index_stocks) #设定股票池,
ContextInfo.day = 20
ContextInfo.ratio = 0.8
ContextInfo.holding_amount = 5
ContextInfo.accountID='testS'

def handlebar(ContextInfo):
buy_condition = False
sell_condition = False
d = ContextInfo.barpos
print(d)
lastdate = timetag_to_datetime(ContextInfo.get_bar_timetag(d - 1), '%Y%m%d')
date = timetag_to_datetime(ContextInfo.get_bar_timetag(d), '%Y%m%d')
print(date)
index_list = ['399381.SZ','399382.SZ','399383.SZ','399384.SZ','399385.SZ','399386.SZ']
return_index = []
weight = ContextInfo.ratio/ContextInfo.holding_amount
size_dict = {}
if (float(date[-4:-2]) != float(lastdate[-4:-2])):
#print '---------------------------------------------------------------------------------'
#print '当前交易日',date,date[-4:-2] 20210101 获取到的月份不一样,这样在每个月初会执行一次这个函数

# 获取的是股票池的
his = ContextInfo.get_history_data(21,'1d','close')

#print "his",his,timetag_to_datetime(ContextInfo.get_bar_timetag(d),"%Y%m%d")
for k in list(his.keys()):
if len(his[k]) == 0:
del his[k]
for index in index_list:
ratio = 0
try:
ratio = (his[index][-2] - his[index][0])/his[index][0]
except KeyError:
print('key error:' + index)
except IndexError:
print('list index out of range:' + index)
return_index.append(ratio)
# 获取指定数内收益率表现最好的行业
best_index = index_list[np.argmax(return_index)]
#print '当前最佳行业是:', ContextInfo.get_stock_name(best_index)[3:]+'行业'
# 获取当天有交易的股票
index_stock = ContextInfo.get_sector(best_index)
stock_available = []
for stock in index_stock:
if ContextInfo.is_suspended_stock(stock) == False: # 是否停牌
stock_available.append(stock)

for stock in stock_available:
if stock in list(his.keys()):
#目前历史流通股本取不到,暂用总股本
if len(his[stock]) >= 2:
stocksize =his[stock][-2] * float(ContextInfo.get_financial_data(['CAPITALSTRUCTURE.total_capital'],[stock],lastdate,date).iloc[0,-1])
size_dict[stock] = stocksize
elif len(his[stock]) == 1:
stocksize =his[stock][-1] * float(ContextInfo.get_financial_data(['CAPITALSTRUCTURE.total_capital'],[stock],lastdate,date).iloc[0,-1])
size_dict[stock] = stocksize
else:
return
size_sorted = sorted(list(size_dict.items()), key = lambda item:item[1]) # 根据股本顺序排序
pre_holding = []

for tuple in size_sorted[-ContextInfo.holding_amount:]: # 最好不要占用关键词
pre_holding.append(tuple[0])
#print '买入备选',pre_holding
#函数下单
if len(pre_holding) > 0:
sellshort_list = []
for stock in list(ContextInfo.MarketPosition.keys()): # 遍历持仓,如果不在当前条件范围内,卖出
if stock not in pre_holding and (stock in list(his.keys())):
order_shares(stock,-ContextInfo.MarketPosition[stock],'lastest',his[stock][-1],ContextInfo,ContextInfo.accountID)
print('sell',stock)
sell_condition = True
sellshort_list.append(stock)
if len(sellshort_list) >0: # 这句多余
for stock in sellshort_list:
del ContextInfo.MarketPosition[stock]

for stock in pre_holding:
if stock not in list(ContextInfo.MarketPosition.keys()): # 买入
Lots = math.floor(ContextInfo.ratio * (1.0/len(pre_holding)) * ContextInfo.capital / (his[stock][-1] * 100))
order_shares(stock,Lots *100,'lastest',his[stock][-1],ContextInfo,ContextInfo.accountID)
print('buy',stock)
buy_condition = True
ContextInfo.MarketPosition[stock] = Lots *100






如果遇到不懂的,可以关注公众号咨询: 查看全部
回测代码如下: 代码里面加入了个人理解的注释。
 
#coding:gbk

'''
回测模型示例(非实盘交易策略)

本策略每隔1个月定时触发计算1000能源(399381.SZ)、1000材料(399382.SZ)、1000工业(399383.SZ)、
1000可选(399384.SZ)、1000消费(399385.SZ)、1000医药(399386.SZ)这几个行业指数过去
20个交易日的收益率并选取了收益率最高的指数的成份股并获取了他们的市值数据
随后把仓位调整至市值最大的5只股票上
该策略在股票指数日线下运行
'''
import numpy as np
import math
def init(ContextInfo):
MarketPosition ={}
ContextInfo.MarketPosition = MarketPosition #初始化持仓
index_universe = ['399381.SZ','399382.SZ','399383.SZ','399384.SZ','399385.SZ','399386.SZ']
index_stocks = []
for index in index_universe:
for stock in ContextInfo.get_sector(index): # 获取指数的成分股
index_stocks.append(stock)
ContextInfo.set_universe(index_universe+index_stocks) #设定股票池,
ContextInfo.day = 20
ContextInfo.ratio = 0.8
ContextInfo.holding_amount = 5
ContextInfo.accountID='testS'

def handlebar(ContextInfo):
buy_condition = False
sell_condition = False
d = ContextInfo.barpos
print(d)
lastdate = timetag_to_datetime(ContextInfo.get_bar_timetag(d - 1), '%Y%m%d')
date = timetag_to_datetime(ContextInfo.get_bar_timetag(d), '%Y%m%d')
print(date)
index_list = ['399381.SZ','399382.SZ','399383.SZ','399384.SZ','399385.SZ','399386.SZ']
return_index = []
weight = ContextInfo.ratio/ContextInfo.holding_amount
size_dict = {}
if (float(date[-4:-2]) != float(lastdate[-4:-2])):
#print '---------------------------------------------------------------------------------'
#print '当前交易日',date,date[-4:-2] 20210101 获取到的月份不一样,这样在每个月初会执行一次这个函数

# 获取的是股票池的
his = ContextInfo.get_history_data(21,'1d','close')

#print "his",his,timetag_to_datetime(ContextInfo.get_bar_timetag(d),"%Y%m%d")
for k in list(his.keys()):
if len(his[k]) == 0:
del his[k]
for index in index_list:
ratio = 0
try:
ratio = (his[index][-2] - his[index][0])/his[index][0]
except KeyError:
print('key error:' + index)
except IndexError:
print('list index out of range:' + index)
return_index.append(ratio)
# 获取指定数内收益率表现最好的行业
best_index = index_list[np.argmax(return_index)]
#print '当前最佳行业是:', ContextInfo.get_stock_name(best_index)[3:]+'行业'
# 获取当天有交易的股票
index_stock = ContextInfo.get_sector(best_index)
stock_available = []
for stock in index_stock:
if ContextInfo.is_suspended_stock(stock) == False: # 是否停牌
stock_available.append(stock)

for stock in stock_available:
if stock in list(his.keys()):
#目前历史流通股本取不到,暂用总股本
if len(his[stock]) >= 2:
stocksize =his[stock][-2] * float(ContextInfo.get_financial_data(['CAPITALSTRUCTURE.total_capital'],[stock],lastdate,date).iloc[0,-1])
size_dict[stock] = stocksize
elif len(his[stock]) == 1:
stocksize =his[stock][-1] * float(ContextInfo.get_financial_data(['CAPITALSTRUCTURE.total_capital'],[stock],lastdate,date).iloc[0,-1])
size_dict[stock] = stocksize
else:
return
size_sorted = sorted(list(size_dict.items()), key = lambda item:item[1]) # 根据股本顺序排序
pre_holding = []

for tuple in size_sorted[-ContextInfo.holding_amount:]: # 最好不要占用关键词
pre_holding.append(tuple[0])
#print '买入备选',pre_holding
#函数下单
if len(pre_holding) > 0:
sellshort_list = []
for stock in list(ContextInfo.MarketPosition.keys()): # 遍历持仓,如果不在当前条件范围内,卖出
if stock not in pre_holding and (stock in list(his.keys())):
order_shares(stock,-ContextInfo.MarketPosition[stock],'lastest',his[stock][-1],ContextInfo,ContextInfo.accountID)
print('sell',stock)
sell_condition = True
sellshort_list.append(stock)
if len(sellshort_list) >0: # 这句多余
for stock in sellshort_list:
del ContextInfo.MarketPosition[stock]

for stock in pre_holding:
if stock not in list(ContextInfo.MarketPosition.keys()): # 买入
Lots = math.floor(ContextInfo.ratio * (1.0/len(pre_holding)) * ContextInfo.capital / (his[stock][-1] * 100))
order_shares(stock,Lots *100,'lastest',his[stock][-1],ContextInfo,ContextInfo.accountID)
print('buy',stock)
buy_condition = True
ContextInfo.MarketPosition[stock] = Lots *100






如果遇到不懂的,可以关注公众号咨询:

优矿回测可转债 代码 教程

李魔佛 发表了文章 • 0 个评论 • 1342 次浏览 • 2021-12-09 00:44 • 来自相关话题

不少投资者在投资的过程中,都想要回测自己的策略或者验证自己的想法. 不少读者也在后台留言,能否写写入门类的教程.

可是碍于非科班出生, 对于编程的一窍不通, 所以大部分止步于简单的数据统计.

比如采用excel对采集来的数据,手工测试与验证, 高级点的可以应用一些excel函数进行简单回测.

这里会有一个烦人且第一大障碍, 就是需要有采集来的数据. 首先保证这个数据的完整性与准确性. 这一步其实已经过滤掉想要回测的80%的人了. 具体优矿支持的数据。
 
 
优矿支持的数据
股票:沪深交易所股票的基本信息以及日/分钟级别的股票行情。 财务报表:沪深港上市公司披露的2007年会计准则变更以来的所有财务报表数据,包含三大报表和财报附注等细节。 公司行为:沪深上市公司业绩预告,业绩快报,IPO,配股,分红,拆股,股改等信息。 基金:场内外各类基金的基本信息,日/分钟级别的场内基金行情,日级别的场外基金净值,以及基金资产配置,收益情况,净值调整等信息。 期货:国内四大期货交易所期货合约的基本信息,日/分钟的期货行情,以及国债期货的转换因子等信息。 指数:国内外指数基本信息,日/分钟级别的指数行情,以及指数成分构成情况,指数成分股权重情况等信息。 港股:香港交易所股票基本信息以及日级别的股票行情。 大宗商品:国内各个品种(包括期货合约可交割品种)的大宗商品现货价格行情,以及产销量,库存等信息。 债券:债券/回购基本信息,日级别的债券/回购行情,以及发行上市,付息,利率,评级和评级变动,债券发行人评级及变动,担保人评级及变动等信息。 期权:上交所期权合约的基本信息,日/分钟级别的期权行情,以及每日盘前静态数据等信息。 宏观产业:中国及全球各国宏观指标,行业经济指标等数据。

特色数据
股票/指数等品种的量化因子库 雪球、股吧等社交媒体数据 主流媒体新闻文本和结构化数据 主流渠道公告文本和结构化数据 淘宝、天猫等电商数据

其实其他的聚框,米宽,箩筐等等,都是大同小异的,本文只是挑选笔者使用比较多的优矿来介绍. 不过现在优矿并不支持实盘.

本文只是做一个量化平台框架的基本介绍, 后续的文章会有进阶, 加入买卖操作, 计算最大回撤, 以及更为复杂的多因子回测. 只要有的数据,基本都可以拿来加入到你的模型之中.
 
##################################################################

因为优矿本身并不支持可转债的交易,所以系统内置的order,buy,sell函数是无法应用到可转债上面。

不过只要能够获取到每日的行情数据,那么我们就可以自己构造一个交易系统。

核心就就是每次保存你的持仓信息,等到下一次调仓时,对持仓进行比较,对于调出的转债进行移除,新加的转债进行加入。 然后统计一下当前市值,记录下来,就可以得到收益率曲线。
 
部分代码如下:import datetime

start = '2018-01-01' # 回测起始时间
end = '2021-05-28' # 回测结束时间
benchmark = 'HS300' # 策略参考标准
freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测
refresh_rate = 5 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd' 时间间隔的单位为交易日,
hold_num = 10 # 持有转债的个数


def initialize(context):
global MyPosition, HighValue, MyCash, Withdraw, HoldRank, HoldNum,Start_Cash
MyPosition = {} #持仓
MyCash = 1000000 #现金
Start_Cash= 1000000
HighValue = MyCash #最高市值
Withdraw = 0 #最大回撤
HoldRank = hold_num #排名多少之后卖出
HoldNum = hold_num #持债支数

def bonds(beginDate=u"20170101",endDate=u"20201215",EB_ENABLE=False):
code_set = set()
df = DataAPI.MktConsBondPremiumGet(SecID=u"",
tickerBond=u"",
beginDate=beginDate,
endDate=endDate,
field=u"",
pandas="1")

cb_df = df.tickerBond.str.startswith(('12', '11'))
df = df[cb_df]
cb_df = df.tickerBond.str.startswith('117')
df = df[~cb_df]
if not EB_ENABLE:
eb = df.secShortNameBond.str.match('\d\d.*?E[123B]') # TODO 判断EB是否过滤
df = df[~eb]

ticker_list =
for _, row in df[['tickerBond', 'secShortNameBond', 'tickerEqu']].iterrows():
if row['tickerBond'] not in code_set:
ticker_list.append((row['tickerBond'], row['secShortNameBond'], row['tickerEqu']))
code_set.add(row['tickerBond'])
return list(code_set)


def handle_data(context):
global MyPosition, HighValue, MyCash, Withdraw, HoldRank, HoldNum,Start_Cash

today_date = context.now.strftime('%Y%m%d')

#每天重新计算双低排名
ticker_list=bonds(today_date,today_date)
data = DataAPI.MktConsBondPerfGet(beginDate=today_date,endDate=today_date,secID='',tickerBond=ticker_list,
tickerEqu=u"",field=u"",pandas="1")
data['secID']=data['tickerBond']
data.set_index('secID',inplace=True)
data['DoubleLow'] = data['closePriceBond'] + data['bondPremRatio']
data = data.sort_values(by="DoubleLow" , ascending=True)
PosValue = MyCash

#抛出不在持有排名HoldRank的
for stock in MyPosition.keys():
try:
CurPrice = data.loc[stock]['closePriceBond']
except:
last_date = (context.now + datetime.timedelta(days=-7)).strftime('%Y%m%d')
CurPrice=get_last_price(stock,last_date,today_date)

PosValue += MyPosition[stock] * CurPrice * 10 #计算当前市值

if stock not in data.index[:HoldRank]:
# 省略若干

log.info('{} 卖出{},{},价格:{}'.format(today_date,stock,name,CurPrice))


if PosValue > HighValue:HighValue = PosValue
if (HighValue - PosValue) / HighValue > Withdraw:Withdraw = (HighValue - PosValue) / HighValue

#买入排在HoldRank内的,总持有数量HoldNum
min_hold = min(HoldRank,len(data.index))
for i in range(min_hold):
if len(MyPosition) >= HoldNum:break
if data.index[i] not in MyPosition.keys():
# 省略若干
log.info('{} 买入{}, {}, 价格{}, 溢价率{}'.format(today_date,data.index[i],name,price,cb_ration))

ratio = (PosValue-Start_Cash)/Start_Cash*100
log.info(today_date + ': 最高市值 ' + str(HighValue) + ' , 当前市值 ' + str(PosValue) + '收益率 : '
+str(ratio)+'% , 最大回撤 ' + str(round(Withdraw*100,2))+'%') [/i][/i]
[i]欢迎讨论探索,星球里面有更多的完整策略与代码,回测数据,结论资源。
 
[/i] 查看全部
不少投资者在投资的过程中,都想要回测自己的策略或者验证自己的想法. 不少读者也在后台留言,能否写写入门类的教程.

可是碍于非科班出生, 对于编程的一窍不通, 所以大部分止步于简单的数据统计.

比如采用excel对采集来的数据,手工测试与验证, 高级点的可以应用一些excel函数进行简单回测.

这里会有一个烦人且第一大障碍, 就是需要有采集来的数据. 首先保证这个数据的完整性与准确性. 这一步其实已经过滤掉想要回测的80%的人了. 具体优矿支持的数据。
 
 
优矿支持的数据
  • 股票:沪深交易所股票的基本信息以及日/分钟级别的股票行情。
  •  
  • 财务报表:沪深港上市公司披露的2007年会计准则变更以来的所有财务报表数据,包含三大报表和财报附注等细节。
  •  
  • 公司行为:沪深上市公司业绩预告,业绩快报,IPO,配股,分红,拆股,股改等信息。
  •  
  • 基金:场内外各类基金的基本信息,日/分钟级别的场内基金行情,日级别的场外基金净值,以及基金资产配置,收益情况,净值调整等信息。
  •  
  • 期货:国内四大期货交易所期货合约的基本信息,日/分钟的期货行情,以及国债期货的转换因子等信息。
  •  
  • 指数:国内外指数基本信息,日/分钟级别的指数行情,以及指数成分构成情况,指数成分股权重情况等信息。
  •  
  • 港股:香港交易所股票基本信息以及日级别的股票行情。
  •  
  • 大宗商品:国内各个品种(包括期货合约可交割品种)的大宗商品现货价格行情,以及产销量,库存等信息。
  •  
  • 债券:债券/回购基本信息,日级别的债券/回购行情,以及发行上市,付息,利率,评级和评级变动,债券发行人评级及变动,担保人评级及变动等信息。
  •  
  • 期权:上交所期权合约的基本信息,日/分钟级别的期权行情,以及每日盘前静态数据等信息。
  •  
  • 宏观产业:中国及全球各国宏观指标,行业经济指标等数据。


特色数据
  • 股票/指数等品种的量化因子库
  •  
  • 雪球、股吧等社交媒体数据
  •  
  • 主流媒体新闻文本和结构化数据
  •  
  • 主流渠道公告文本和结构化数据
  •  
  • 淘宝、天猫等电商数据


其实其他的聚框,米宽,箩筐等等,都是大同小异的,本文只是挑选笔者使用比较多的优矿来介绍. 不过现在优矿并不支持实盘.

本文只是做一个量化平台框架的基本介绍, 后续的文章会有进阶, 加入买卖操作, 计算最大回撤, 以及更为复杂的多因子回测. 只要有的数据,基本都可以拿来加入到你的模型之中.
 
##################################################################

因为优矿本身并不支持可转债的交易,所以系统内置的order,buy,sell函数是无法应用到可转债上面。

不过只要能够获取到每日的行情数据,那么我们就可以自己构造一个交易系统。

核心就就是每次保存你的持仓信息,等到下一次调仓时,对持仓进行比较,对于调出的转债进行移除,新加的转债进行加入。 然后统计一下当前市值,记录下来,就可以得到收益率曲线。
 
部分代码如下:
import datetime

start = '2018-01-01' # 回测起始时间
end = '2021-05-28' # 回测结束时间
benchmark = 'HS300' # 策略参考标准
freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测
refresh_rate = 5 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd' 时间间隔的单位为交易日,
hold_num = 10 # 持有转债的个数


def initialize(context):
global MyPosition, HighValue, MyCash, Withdraw, HoldRank, HoldNum,Start_Cash
MyPosition = {} #持仓
MyCash = 1000000 #现金
Start_Cash= 1000000
HighValue = MyCash #最高市值
Withdraw = 0 #最大回撤
HoldRank = hold_num #排名多少之后卖出
HoldNum = hold_num #持债支数

def bonds(beginDate=u"20170101",endDate=u"20201215",EB_ENABLE=False):
code_set = set()
df = DataAPI.MktConsBondPremiumGet(SecID=u"",
tickerBond=u"",
beginDate=beginDate,
endDate=endDate,
field=u"",
pandas="1")

cb_df = df.tickerBond.str.startswith(('12', '11'))
df = df[cb_df]
cb_df = df.tickerBond.str.startswith('117')
df = df[~cb_df]
if not EB_ENABLE:
eb = df.secShortNameBond.str.match('\d\d.*?E[123B]') # TODO 判断EB是否过滤
df = df[~eb]

ticker_list =
for _, row in df[['tickerBond', 'secShortNameBond', 'tickerEqu']].iterrows():
if row['tickerBond'] not in code_set:
ticker_list.append((row['tickerBond'], row['secShortNameBond'], row['tickerEqu']))
code_set.add(row['tickerBond'])
return list(code_set)


def handle_data(context):
global MyPosition, HighValue, MyCash, Withdraw, HoldRank, HoldNum,Start_Cash

today_date = context.now.strftime('%Y%m%d')

#每天重新计算双低排名
ticker_list=bonds(today_date,today_date)
data = DataAPI.MktConsBondPerfGet(beginDate=today_date,endDate=today_date,secID='',tickerBond=ticker_list,
tickerEqu=u"",field=u"",pandas="1")
data['secID']=data['tickerBond']
data.set_index('secID',inplace=True)
data['DoubleLow'] = data['closePriceBond'] + data['bondPremRatio']
data = data.sort_values(by="DoubleLow" , ascending=True)
PosValue = MyCash

#抛出不在持有排名HoldRank的
for stock in MyPosition.keys():
try:
CurPrice = data.loc[stock]['closePriceBond']
except:
last_date = (context.now + datetime.timedelta(days=-7)).strftime('%Y%m%d')
CurPrice=get_last_price(stock,last_date,today_date)

PosValue += MyPosition[stock] * CurPrice * 10 #计算当前市值

if stock not in data.index[:HoldRank]:
# 省略若干

log.info('{} 卖出{},{},价格:{}'.format(today_date,stock,name,CurPrice))


if PosValue > HighValue:HighValue = PosValue
if (HighValue - PosValue) / HighValue > Withdraw:Withdraw = (HighValue - PosValue) / HighValue

#买入排在HoldRank内的,总持有数量HoldNum
min_hold = min(HoldRank,len(data.index))
for i in range(min_hold):
if len(MyPosition) >= HoldNum:break
if data.index[i] not in MyPosition.keys():
# 省略若干
log.info('{} 买入{}, {}, 价格{}, 溢价率{}'.format(today_date,data.index[i],name,price,cb_ration))

ratio = (PosValue-Start_Cash)/Start_Cash*100
log.info(today_date + ': 最高市值 ' + str(HighValue) + ' , 当前市值 ' + str(PosValue) + '收益率 : '
+str(ratio)+'% , 最大回撤 ' + str(round(Withdraw*100,2))+'%') [/i][/i]

[i]欢迎讨论探索,星球里面有更多的完整策略与代码,回测数据,结论资源。
 
[/i]

QMT无法下载python库

李魔佛 发表了文章 • 0 个评论 • 485 次浏览 • 2021-12-08 21:58 • 来自相关话题

 
 点击打开大图

因为一直有很多朋友和我反馈,QMT经常下载python库失败。 我自己也试了下。的确,这个软件经常抽风,软件问题,实在没有办法。
券商软件做的这么垃圾的,也是第一次见。 换了谁也不想用,老是卡在这种设置问题,然后客服也找不到,也是挺郁闷的。
暂时不确定是软件本身的问题,还是券商自己的问题。
 
##### 后续更新:
券商反馈,在开盘期间做了限流,导致下载速度极慢。 在晚上的时间段,下载速度很快,一下子就下载好了。
几台服务器同时下好了。

  查看全部
 
 点击打开大图

因为一直有很多朋友和我反馈,QMT经常下载python库失败。 我自己也试了下。的确,这个软件经常抽风,软件问题,实在没有办法。
券商软件做的这么垃圾的,也是第一次见。 换了谁也不想用,老是卡在这种设置问题,然后客服也找不到,也是挺郁闷的。
暂时不确定是软件本身的问题,还是券商自己的问题。
 
##### 后续更新:
券商反馈,在开盘期间做了限流,导致下载速度极慢。 在晚上的时间段,下载速度很快,一下子就下载好了。
几台服务器同时下好了。

 

鹏华全球高收益债 与 鹏华全球中短债 同一个基金的姐妹基金暴雷

李魔佛 发表了文章 • 0 个评论 • 534 次浏览 • 2021-11-16 01:40 • 来自相关话题

看之前的报道:2018年末鹏华全球高收益债持有人户数为25445户,比成立时增长了10倍



购买过鹏华全球高收益债的基金账户数已超16.52万



投资者平均持仓鹏华全球高收益债302.21天



持仓鹏华全球高收益债的客户中,60岁以上的客户平均收益最高,姜还是老的辣



持有鹏华全球高收益债的客户账户平均资产为54140.93元



共有20413位客户定投过鹏华全球高收益债,平均每人定投15.72次,平均持仓554天,平均盈利3315.71元



鹏华全球高收益债的平均复购间隔时间仅为8.68天,复购率为69.43%



因“申购费率优惠”共为鹏华全球高收益债投资者节省了3318万元,最精明的个人客户共节省了118万元的申购费 

持仓鹏华全球高收益债的客户中,60岁以上的客户平均收益最高,姜还是老的辣。

惨了,这些老年人的退休金就这样打水漂了哦。
 
买的地产债,暴雷,实属也无奈。
 
现在也可以抄一些低,最好分批,因为不知道后面会不会继续跌。 查看全部
看之前的报道:
2018年末鹏华全球高收益债持有人户数为25445户,比成立时增长了10倍 



购买过鹏华全球高收益债的基金账户数已超16.52万



投资者平均持仓鹏华全球高收益债302.21天



持仓鹏华全球高收益债的客户中,60岁以上的客户平均收益最高,姜还是老的辣



持有鹏华全球高收益债的客户账户平均资产为54140.93元



共有20413位客户定投过鹏华全球高收益债,平均每人定投15.72次,平均持仓554天,平均盈利3315.71元



鹏华全球高收益债的平均复购间隔时间仅为8.68天,复购率为69.43%



因“申购费率优惠”共为鹏华全球高收益债投资者节省了3318万元,最精明的个人客户共节省了118万元的申购费
 

持仓鹏华全球高收益债的客户中,60岁以上的客户平均收益最高,姜还是老的辣。

惨了,这些老年人的退休金就这样打水漂了哦。
 
买的地产债,暴雷,实属也无奈。
 
现在也可以抄一些低,最好分批,因为不知道后面会不会继续跌。

30天掌握Golang 教程系列 第一课 基础知识

量化大师 发表了文章 • 0 个评论 • 863 次浏览 • 2021-08-04 01:15 • 来自相关话题

基础练习:
这里有一个Golang的练习库,输入基础入门的资料。 大家可以先练习练习:
https://github.com/Rockyzsu/GolangLearning/tree/master/Go-Notes
 

基础语法是没办法绕过的,如果前期不打扎实,后期也会不断来回折腾。除非你做的项目只是一次性的,否则,磨刀不误砍柴工,还是打扎实。 把上面的github的例子弄懂,这个Go-notes的好处是,如果遇到你不懂的,可以马上查找相关的资料。如果全部都懂的话,可以进阶到第二阶段。
个人觉得还是得要多看看别人的代码,看多了,其实你写代码也会有灵感。(虽然有些人写的代码很烂,但是也可以自己做过标号,避免自己以后写出同样的代码。) 

PS: 本来我想从0开始写教程,不过网上其实也有很多教程,很多视频。 也有不少的书籍可以学。所以就没有必要重复造轮子了。
 
而实际的情况是,入门的人数需求是100个人,而进阶的需求是只有60个人,而深入理解并需要对应的教程的,可能只有20人不到。
 
所以想着写golang教程,最受欢迎的其实是hello world教程。
 
实际写起来也很容易,无法就是if - else,for, 切片,数组,通道,goroutine,结构体等。
不过对于笔者的能力提升是没有一点点用处的,当日提升知名度除外。
 
所以入门系列的基础课,我这里就一比带过。可以留一些比较容易踩到的坑。
 
当然这个基础知识不可能 第一天就全部搞定。 可以多花几天甚至一周的时间。
  查看全部
基础练习:
这里有一个Golang的练习库,输入基础入门的资料。 大家可以先练习练习:
https://github.com/Rockyzsu/GolangLearning/tree/master/Go-Notes
 

基础语法是没办法绕过的,如果前期不打扎实,后期也会不断来回折腾。除非你做的项目只是一次性的,否则,磨刀不误砍柴工,还是打扎实。 把上面的github的例子弄懂,这个Go-notes的好处是,如果遇到你不懂的,可以马上查找相关的资料。如果全部都懂的话,可以进阶到第二阶段。
个人觉得还是得要多看看别人的代码,看多了,其实你写代码也会有灵感。(虽然有些人写的代码很烂,但是也可以自己做过标号,避免自己以后写出同样的代码。) 

PS: 本来我想从0开始写教程,不过网上其实也有很多教程,很多视频。 也有不少的书籍可以学。所以就没有必要重复造轮子了。
 
而实际的情况是,入门的人数需求是100个人,而进阶的需求是只有60个人,而深入理解并需要对应的教程的,可能只有20人不到。
 
所以想着写golang教程,最受欢迎的其实是hello world教程。
 
实际写起来也很容易,无法就是if - else,for, 切片,数组,通道,goroutine,结构体等。
不过对于笔者的能力提升是没有一点点用处的,当日提升知名度除外。
 
所以入门系列的基础课,我这里就一比带过。可以留一些比较容易踩到的坑。
 
当然这个基础知识不可能 第一天就全部搞定。 可以多花几天甚至一周的时间。
 

优矿的可转债的YTM数据为空 nan

李魔佛 发表了文章 • 0 个评论 • 871 次浏览 • 2021-05-31 09:18 • 来自相关话题

获取函数:DataAPI.MktBonddGet(secID=u"",ticker=u"122560",tradeDate=u"",beginDate=u"20180301",endDate=u"20180315",field=u"",pandas="1")
注意YTM哪一列全是Nan





 
脏数据太多了,吐槽一波。 查看全部
获取函数:
DataAPI.MktBonddGet(secID=u"",ticker=u"122560",tradeDate=u"",beginDate=u"20180301",endDate=u"20180315",field=u"",pandas="1")

注意YTM哪一列全是Nan

loDPX1TA71.png

 
脏数据太多了,吐槽一波。

Ptrade策略示例

李魔佛 发表了文章 • 0 个评论 • 1512 次浏览 • 2021-05-26 19:02 • 来自相关话题

策略示例
 
集合竞价追涨停策略def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
#每天9:23分运行集合竞价处理函数
run_daily(context, aggregate_auction_func, time='9:23')

def aggregate_auction_func(context):
stock = g.security
#最新价
snapshot = get_snapshot(stock)
price = snapshot[stock]['last_px']
#涨停价
up_limit = snapshot[stock]['up_px']
#如果最新价不小于涨停价,买入
if float(price) >= float(up_limit):
order(g.security, 100, limit_price=up_limit)

def handle_data(context, data):
pass
tick级别均线策略def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
#每3秒运行一次主函数
run_interval(context, func, seconds=3)

#盘前准备历史数据
def before_trading_start(context, data):
history = get_history(10, '1d', 'close', g.security, fq='pre', include=False)
g.close_array = history['close'].values

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def func(context):

stock = g.security

#获取最新价
snapshot = get_snapshot(stock)
price = snapshot[stock]['last_px']

# 得到五日均线价格
days = 5
ma5 = get_MA_day(stock, days, g.close_array[-4:], price)
# 得到十日均线价格
days = 10
ma10 = get_MA_day(stock, days, g.close_array[-9:], price)

# 得到当前资金余额
cash = context.portfolio.cash

# 如果当前有余额,并且五日均线大于十日均线
if ma5 > ma10:
# 用所有 cash 买入股票
order_value(stock, cash)
# 记录这次买入
log.info("Buying %s" % (stock))

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(stock).amount > 0:
# 全部卖出
order_target(stock, 0)
# 记录这次卖出
log.info("Selling %s" % (stock))

#计算实时均线函数
def get_MA_day(stock,days,close_array,current_price):
close_sum = close_array[-(days-1):].sum()
MA = (current_price + close_sum)/days
return MA

def handle_data(context, data):
pass
双均线策略def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
pass

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def handle_data(context, data):
security = g.security

#得到十日历史价格
df = get_history(10, '1d', 'close', security, fq=None, include=False)

# 得到五日均线价格
ma5 = round(df['close'][-5:].mean(), 3)

# 得到十日均线价格
ma10 = round(df['close'][-10:].mean(), 3)

# 取得昨天收盘价
price = data[security]['close']

# 得到当前资金余额
cash = context.portfolio.cash

# 如果当前有余额,并且五日均线大于十日均线
if ma5 > ma10:
# 用所有 cash 买入股票
order_value(security, cash)
# 记录这次买入
log.info("Buying %s" % (security))

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(security).amount > 0:
# 全部卖出
order_target(security, 0)
# 记录这次卖出
log.info("Selling %s" % (security))
 macd策略

指数平滑均线函数,以price计算,可以选择收盘、开盘价等价格,N为时间周期,m用于计算平滑系数a=m/(N+1),EXPMA1为前一日值def f_expma(N,m,EXPMA1,price):
a = m/(N+1)
EXPMA2 = a * price + (1 - a)*EXPMA1
return EXPMA2 #2为后一天值

#定义macd函数,输入平滑系数参数、前一日值,输出当日值
def macd(N1,N2,N3,m,EXPMA12_1,EXPMA26_1,DEA1,price):
EXPMA12_2 = f_expma(N1,m,EXPMA12_1,price)
EXPMA26_2 = f_expma(N2,m,EXPMA26_1,price)
DIF2 = EXPMA12_2 - EXPMA26_2
a = m/(N3+1)
DEA2 = a * DIF2 + (1 - a)*DEA1
BAR2=2*(DIF2-DEA2)
return EXPMA12_2,EXPMA26_2,DIF2,DEA2,BAR2

def initialize(context):
global init_price
init_price = None
# 获取沪深300股票
g.security = get_index_stocks('000300.SS')
#g.security = ['600570.SS']
# 设置我们要操作的股票池, 这里我们只操作一支股票
set_universe(g.security)

def handle_data(context, data):
# 获取历史数据,这里只获取了2天的数据,如果希望最终MACD指标结果更准确最好是获取
# 从股票上市至今的所有历史数据,即增加获取的天数
close_price = get_history(2, '1d', field='close', security_list=g.security)
#如果是停牌不进行计算
for security in g.security:
if data[security].is_open >0:
global init_price,EXPMA12_1,EXPMA26_1,EXPMA12_2,EXPMA26_2,DIF1,DIF2,DEA1,DEA2
if init_price is None:
init_price = close_price[security].mean()#nan和N-1个数,mean为N-1个数的均值
EXPMA12_1 = init_price
EXPMA26_1 = init_price
DIF1 = init_price
DEA1 = init_price
# m用于计算平滑系数a=m/(N+1)
m = 2.0
#设定指数平滑基期数
N1 = 12
N2 = 26
N3 = 9
EXPMA12_2,EXPMA26_2,DIF2,DEA2,BAR2 = macd(N1,N2,N3,m,EXPMA12_1,EXPMA26_1,DEA1,close_price[security][-1])
# 取得当前价格
current_price = data[security].price
# 取得当前的现金
cash = context.portfolio.cash
# DIF、DEA均为正,DIF向上突破DEA,买入信号参考
if DIF2 > 0 and DEA2 > 0 and DIF1 < DEA1 and DIF2 > DEA2:
# 计算可以买多少只股票
number_of_shares = int(cash/current_price)
# 购买量大于0时,下单
if number_of_shares > 0:
# 以市单价买入股票,日回测时即是开盘价
order(security, +number_of_shares)
# 记录这次买入
log.info("Buying %s" % (security))
# DIF、DEA均为负,DIF向下突破DEA,卖出信号参考
elif DIF2 < 0 and DEA2 < 0 and DIF1 > DEA1 and DIF2 < DEA2 and get_position(security).amount > 0:
# 卖出所有股票,使这只股票的最终持有量为0
order_target(security, 0)
# 记录这次卖出
log.info("Selling %s" % (security))
# 将今日的值赋给全局变量作为下一次前一日的值
DEA1 = DEA2
DIF1 = DIF2
EXPMA12_1 = EXPMA12_2
EXPMA26_1 = EXPMA26_2
如果需要开通Ptrade量化接口,只需资金50W存放一周即可。
交易费率也很便宜,股票万一,基金万0.6, 可转债百万分之二。
量化接口不需要收取任何费用。
有意者可以扫码开户: 查看全部
策略示例
 
集合竞价追涨停策略
def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
#每天9:23分运行集合竞价处理函数
run_daily(context, aggregate_auction_func, time='9:23')

def aggregate_auction_func(context):
stock = g.security
#最新价
snapshot = get_snapshot(stock)
price = snapshot[stock]['last_px']
#涨停价
up_limit = snapshot[stock]['up_px']
#如果最新价不小于涨停价,买入
if float(price) >= float(up_limit):
order(g.security, 100, limit_price=up_limit)

def handle_data(context, data):
pass

tick级别均线策略
def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
#每3秒运行一次主函数
run_interval(context, func, seconds=3)

#盘前准备历史数据
def before_trading_start(context, data):
history = get_history(10, '1d', 'close', g.security, fq='pre', include=False)
g.close_array = history['close'].values

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def func(context):

stock = g.security

#获取最新价
snapshot = get_snapshot(stock)
price = snapshot[stock]['last_px']

# 得到五日均线价格
days = 5
ma5 = get_MA_day(stock, days, g.close_array[-4:], price)
# 得到十日均线价格
days = 10
ma10 = get_MA_day(stock, days, g.close_array[-9:], price)

# 得到当前资金余额
cash = context.portfolio.cash

# 如果当前有余额,并且五日均线大于十日均线
if ma5 > ma10:
# 用所有 cash 买入股票
order_value(stock, cash)
# 记录这次买入
log.info("Buying %s" % (stock))

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(stock).amount > 0:
# 全部卖出
order_target(stock, 0)
# 记录这次卖出
log.info("Selling %s" % (stock))

#计算实时均线函数
def get_MA_day(stock,days,close_array,current_price):
close_sum = close_array[-(days-1):].sum()
MA = (current_price + close_sum)/days
return MA

def handle_data(context, data):
pass

双均线策略
def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
pass

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def handle_data(context, data):
security = g.security

#得到十日历史价格
df = get_history(10, '1d', 'close', security, fq=None, include=False)

# 得到五日均线价格
ma5 = round(df['close'][-5:].mean(), 3)

# 得到十日均线价格
ma10 = round(df['close'][-10:].mean(), 3)

# 取得昨天收盘价
price = data[security]['close']

# 得到当前资金余额
cash = context.portfolio.cash

# 如果当前有余额,并且五日均线大于十日均线
if ma5 > ma10:
# 用所有 cash 买入股票
order_value(security, cash)
# 记录这次买入
log.info("Buying %s" % (security))

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(security).amount > 0:
# 全部卖出
order_target(security, 0)
# 记录这次卖出
log.info("Selling %s" % (security))

 macd策略

指数平滑均线函数,以price计算,可以选择收盘、开盘价等价格,N为时间周期,m用于计算平滑系数a=m/(N+1),EXPMA1为前一日值
def f_expma(N,m,EXPMA1,price):
a = m/(N+1)
EXPMA2 = a * price + (1 - a)*EXPMA1
return EXPMA2 #2为后一天值

#定义macd函数,输入平滑系数参数、前一日值,输出当日值
def macd(N1,N2,N3,m,EXPMA12_1,EXPMA26_1,DEA1,price):
EXPMA12_2 = f_expma(N1,m,EXPMA12_1,price)
EXPMA26_2 = f_expma(N2,m,EXPMA26_1,price)
DIF2 = EXPMA12_2 - EXPMA26_2
a = m/(N3+1)
DEA2 = a * DIF2 + (1 - a)*DEA1
BAR2=2*(DIF2-DEA2)
return EXPMA12_2,EXPMA26_2,DIF2,DEA2,BAR2

def initialize(context):
global init_price
init_price = None
# 获取沪深300股票
g.security = get_index_stocks('000300.SS')
#g.security = ['600570.SS']
# 设置我们要操作的股票池, 这里我们只操作一支股票
set_universe(g.security)

def handle_data(context, data):
# 获取历史数据,这里只获取了2天的数据,如果希望最终MACD指标结果更准确最好是获取
# 从股票上市至今的所有历史数据,即增加获取的天数
close_price = get_history(2, '1d', field='close', security_list=g.security)
#如果是停牌不进行计算
for security in g.security:
if data[security].is_open >0:
global init_price,EXPMA12_1,EXPMA26_1,EXPMA12_2,EXPMA26_2,DIF1,DIF2,DEA1,DEA2
if init_price is None:
init_price = close_price[security].mean()#nan和N-1个数,mean为N-1个数的均值
EXPMA12_1 = init_price
EXPMA26_1 = init_price
DIF1 = init_price
DEA1 = init_price
# m用于计算平滑系数a=m/(N+1)
m = 2.0
#设定指数平滑基期数
N1 = 12
N2 = 26
N3 = 9
EXPMA12_2,EXPMA26_2,DIF2,DEA2,BAR2 = macd(N1,N2,N3,m,EXPMA12_1,EXPMA26_1,DEA1,close_price[security][-1])
# 取得当前价格
current_price = data[security].price
# 取得当前的现金
cash = context.portfolio.cash
# DIF、DEA均为正,DIF向上突破DEA,买入信号参考
if DIF2 > 0 and DEA2 > 0 and DIF1 < DEA1 and DIF2 > DEA2:
# 计算可以买多少只股票
number_of_shares = int(cash/current_price)
# 购买量大于0时,下单
if number_of_shares > 0:
# 以市单价买入股票,日回测时即是开盘价
order(security, +number_of_shares)
# 记录这次买入
log.info("Buying %s" % (security))
# DIF、DEA均为负,DIF向下突破DEA,卖出信号参考
elif DIF2 < 0 and DEA2 < 0 and DIF1 > DEA1 and DIF2 < DEA2 and get_position(security).amount > 0:
# 卖出所有股票,使这只股票的最终持有量为0
order_target(security, 0)
# 记录这次卖出
log.info("Selling %s" % (security))
# 将今日的值赋给全局变量作为下一次前一日的值
DEA1 = DEA2
DIF1 = DIF2
EXPMA12_1 = EXPMA12_2
EXPMA26_1 = EXPMA26_2

如果需要开通Ptrade量化接口,只需资金50W存放一周即可。
交易费率也很便宜,股票万一,基金万0.6, 可转债百万分之二。
量化接口不需要收取任何费用。
有意者可以扫码开户:

火币登录时提示 谷歌验证码错误 无法登录

绫波丽 发表了文章 • 0 个评论 • 1777 次浏览 • 2021-05-23 14:04 • 来自相关话题

安全器使用的时谷歌身份验证器,反复登录几次后一直提示谷歌验证码错误,,请重新输入。
难度凉凉了吗??
和客服聊了下,只好解绑。或者用app登录
安全器使用的时谷歌身份验证器,反复登录几次后一直提示谷歌验证码错误,,请重新输入。
难度凉凉了吗??
和客服聊了下,只好解绑。或者用app登录

coinegg.fun coinegg币蛋真垃圾 入金最低要10000

李魔佛 发表了文章 • 0 个评论 • 1231 次浏览 • 2021-05-10 20:38 • 来自相关话题

 点击查看大图

请在10000-1000000之间设置金额。。。
 这样子玩,迟早没有人气的了。韭菜都去了隔壁火币平台了。
 

urtsGfHmox.png


 点击查看大图

请在10000-1000000之间设置金额。。。
 这样子玩,迟早没有人气的了。韭菜都去了隔壁火币平台了。