python获取A股上市公司的盈利能力

李魔佛 发表了文章 • 0 个评论 • 6719 次浏览 • 2018-01-04 16:09 • 来自相关话题

利用tushare库,可以很方便的获取A股上市公司的基本面信息。
比如企业的盈利能力。
 import tushare as ts
#获取2017年第3季度的盈利能力数据
ts.get_profit_data(2017,3)返回的结果:
 
按年度、季度获取盈利能力数据,结果返回的数据属性说明如下:
code,代码 
name,名称 
roe,净资产收益率(%)
 net_profit_ratio,净利率(%) 
gross_profit_rate,毛利率(%) 
net_profits,净利润(百万元)  #这里的官网信息有误,单位应该是百万
esp,每股收益 
business_income,营业收入(百万元) 
bips,每股主营业务收入(元)
 
例如返回如下结果:
 
    code   name    roe  net_profit_ratio  gross_profit_rate  net_profits  \
  000717   韶钢松山  79.22              9.44            14.1042    1750.2624
  600793   宜宾纸业  65.40             13.31             7.9084     100.6484
  600306    商业城  63.19             18.55            17.8601     114.9175
  000526  *ST紫学  61.03              2.78            31.1212      63.6477
  600768   宁波富邦  57.83             14.95             2.7349      88.3171
 
原创,转载请注明:
http://30daydo.com/article/260
  查看全部
利用tushare库,可以很方便的获取A股上市公司的基本面信息。
比如企业的盈利能力。
 
import tushare as ts
#获取2017年第3季度的盈利能力数据
ts.get_profit_data(2017,3)
返回的结果:
 
按年度、季度获取盈利能力数据,结果返回的数据属性说明如下:
code,代码 
name,名称 
roe,净资产收益率(%)
 net_profit_ratio,净利率(%) 
gross_profit_rate,毛利率(%) 
net_profits,净利润(百万元)  #这里的官网信息有误,单位应该是百万
esp,每股收益 
business_income,营业收入(百万元) 
bips,每股主营业务收入(元)
 
例如返回如下结果:
 
    code   name    roe  net_profit_ratio  gross_profit_rate  net_profits  \
  000717   韶钢松山  79.22              9.44            14.1042    1750.2624
  600793   宜宾纸业  65.40             13.31             7.9084     100.6484
  600306    商业城  63.19             18.55            17.8601     114.9175
  000526  *ST紫学  61.03              2.78            31.1212      63.6477
  600768   宁波富邦  57.83             14.95             2.7349      88.3171
 
原创,转载请注明:
http://30daydo.com/article/260
 

python获取股票年涨跌幅排名

李魔佛 发表了文章 • 4 个评论 • 9242 次浏览 • 2017-12-30 23:11 • 来自相关话题

2017还剩一天就结束了,而A股在昨天已经收官了。 对于大部分投资者来说,这一年能跑赢指数已经很厉害的了,因为指数被权重股拉的失真了,上证指数的分时白线和黄线经常出现张开的大口,白线在上,黄线在下。
 
作为年终回顾,首先看看A股市场2017的总体涨跌幅排名。
 
下面函数是用来获取个股某个时间段的涨跌幅。code是股票代码,start为开始时间段,end为结束时间段。def profit(code,start,end):
try:
df=ts.get_k_data(code,start=start,end=end)
except Exception,e:
print e
return None
try:
p=(df['close'].iloc[-1]-df['close'].iloc[0])/df['close'].iloc[0]*100.00
except Exception,e:
print e
return None
return round(p,2)
如果要获取华大基因的2017年涨幅,可以使用profit('300678','2016-12-31','2017-12-31')
需要注意的是,需要添加一个except的异常处理,因为部分个股停牌时间超过一年,所以该股的收盘价都是空的,这种情况就返回一个None值,在dataframe里就是NaN。
 
剩下了的就是枚举所有A股的个股代码了,然后把遍历所有代码,调用profit函数即可。def price_change():
basic=ts.get_stock_basics()
pro=

for code in basic.index.values:
print code
p=profit(code,'2016-12-31','2017-12-31')
pro.append(p)
basic['price_change']=pro
basic.to_csv('2017_all_price_change.xls',encoding='gbk')
df=pd.read_csv('2017_all_price_change.xls',encoding='gbk')
df.to_excel('2017_all_price_change.xls',encoding='gbk')
结果保存到2017_all_price_change.xls中,里面有个股的基本信息,还追加了一列2017年的涨跌幅,price_change
 
最后我们把price_change按照从高到低进行排序。 看看哪些个股排名靠前。def analysis():
df=pd.read_excel('2017_all_price_change.xls',encoding='gbk')
df=df.sort_values(by='price_change',ascending=False)
df.to_excel('2017-year.xls',encoding='gbk')
最终保存的文件为2017-year.xls,当然你也可以保存到mysql的数据库当中。engine=get_engine('stock')
df.to_sql('2017years',engine)

其中get_engine() 函数如下定义:def get_engine(db):
engine = create_engine('mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST, MYSQL_PORT, db))
return engine
只需要把你的mysql数据库的用户名密码等变量加上去就可以了。
 
最终的结果如下:






点击查看大图 

附件是导出来的excel格式的数据,你们可以拿去参考。

下一篇我们来学习统计个股的信息,比如哪类股涨得好,哪类股具有相关性,哪类股和大盘走向类似等等。
 
原文链接:http://30daydo.com/article/258
转载请注明出处
 
附件

2017-year.zip


  查看全部
2017还剩一天就结束了,而A股在昨天已经收官了。 对于大部分投资者来说,这一年能跑赢指数已经很厉害的了,因为指数被权重股拉的失真了,上证指数的分时白线和黄线经常出现张开的大口,白线在上,黄线在下。
 
作为年终回顾,首先看看A股市场2017的总体涨跌幅排名。
 
下面函数是用来获取个股某个时间段的涨跌幅。code是股票代码,start为开始时间段,end为结束时间段。
def profit(code,start,end):
try:
df=ts.get_k_data(code,start=start,end=end)
except Exception,e:
print e
return None
try:
p=(df['close'].iloc[-1]-df['close'].iloc[0])/df['close'].iloc[0]*100.00
except Exception,e:
print e
return None
return round(p,2)

如果要获取华大基因的2017年涨幅,可以使用
profit('300678','2016-12-31','2017-12-31')

需要注意的是,需要添加一个except的异常处理,因为部分个股停牌时间超过一年,所以该股的收盘价都是空的,这种情况就返回一个None值,在dataframe里就是NaN。
 
剩下了的就是枚举所有A股的个股代码了,然后把遍历所有代码,调用profit函数即可。
def price_change():
basic=ts.get_stock_basics()
pro=

for code in basic.index.values:
print code
p=profit(code,'2016-12-31','2017-12-31')
pro.append(p)
basic['price_change']=pro
basic.to_csv('2017_all_price_change.xls',encoding='gbk')
df=pd.read_csv('2017_all_price_change.xls',encoding='gbk')
df.to_excel('2017_all_price_change.xls',encoding='gbk')

结果保存到2017_all_price_change.xls中,里面有个股的基本信息,还追加了一列2017年的涨跌幅,price_change
 
最后我们把price_change按照从高到低进行排序。 看看哪些个股排名靠前。
def analysis():
df=pd.read_excel('2017_all_price_change.xls',encoding='gbk')
df=df.sort_values(by='price_change',ascending=False)
df.to_excel('2017-year.xls',encoding='gbk')

最终保存的文件为2017-year.xls,当然你也可以保存到mysql的数据库当中。
engine=get_engine('stock')
df.to_sql('2017years',engine)

其中get_engine() 函数如下定义:
def get_engine(db):
engine = create_engine('mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST, MYSQL_PORT, db))
return engine

只需要把你的mysql数据库的用户名密码等变量加上去就可以了。
 
最终的结果如下:


2017-stock_副本.png

点击查看大图 

附件是导出来的excel格式的数据,你们可以拿去参考。

下一篇我们来学习统计个股的信息,比如哪类股涨得好,哪类股具有相关性,哪类股和大盘走向类似等等。
 
原文链接:http://30daydo.com/article/258
转载请注明出处
 
附件

 

dataframe reindex和reset_index区别

李魔佛 发表了文章 • 0 个评论 • 83217 次浏览 • 2017-12-30 15:58 • 来自相关话题

reset_index的作用是重新设置dataframe的index,范围为0~len(df)。 df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]})
df2 = pd.DataFrame({'A': [6], 'B': [60]})
print('df', df)
print('df2', df2)

df_x = [df, df2]
result = pd.concat(df_x)
print('first result ', result) 
上面代码把df和df2合并为一个result,但是result的index是乱的。





 
那么执行result2= result.reset_index()
得到如下的result2: (默认只是返回一个copy,原来的result没有发生改变,所以需要副本赋值给result2)





可以看到,原来的一列index现在变成了columns之一,新的index为[0,1,2,3,4,5]
如果添加参数 reset_index(drop=True) 那么原index会被丢弃,不会显示为一个新列。result2 = result.reset_index(drop=True)



 
reindex的作用是按照原有的列进行重新生成一个新的df。
 
还是使用上面的代码
result目前是df和df2的合并序列。
如下:




 
可以看到index为[0,1,2,3,4,0]
执行 result3 = result.reindex(columns=['A','C'])




 
可以看到,原index并没有发生改变,而列变成了A和C,因为C是不存在的,所以使用了NaB填充,这个值的内容可以自己填充,可以改为默认填充0或者任意你想要的数据。reindex(columns=..)的作用类似于重新把列的顺序整理一遍, 而使用reindex(index=....) 则按照行重新整理一遍。

原文链接:http://30daydo.com/article/257 
欢迎转载,注明出处
  查看全部
reset_index的作用是重新设置dataframe的index,范围为0~len(df)。
    df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]})
df2 = pd.DataFrame({'A': [6], 'B': [60]})
print('df', df)
print('df2', df2)

df_x = [df, df2]
result = pd.concat(df_x)
print('first result ', result)
 
上面代码把df和df2合并为一个result,但是result的index是乱的。

df4.PNG

 
那么执行
result2= result.reset_index()

得到如下的result2: (默认只是返回一个copy,原来的result没有发生改变,所以需要副本赋值给result2)

df5.PNG

可以看到,原来的一列index现在变成了columns之一,新的index为[0,1,2,3,4,5]
如果添加参数 reset_index(drop=True) 那么原index会被丢弃,不会显示为一个新列。
result2 = result.reset_index(drop=True)
df6.PNG

 
reindex的作用是按照原有的列进行重新生成一个新的df。
 
还是使用上面的代码
result目前是df和df2的合并序列。
如下:
df7.PNG

 
可以看到index为[0,1,2,3,4,0]
执行 
result3 = result.reindex(columns=['A','C'])

df8.PNG

 
可以看到,原index并没有发生改变,而列变成了A和C,因为C是不存在的,所以使用了NaB填充,这个值的内容可以自己填充,可以改为默认填充0或者任意你想要的数据。reindex(columns=..)的作用类似于重新把列的顺序整理一遍, 而使用reindex(index=....) 则按照行重新整理一遍。

原文链接:http://30daydo.com/article/257 
欢迎转载,注明出处
 

dataframe的index索引是否可以重复

李魔佛 发表了文章 • 0 个评论 • 11429 次浏览 • 2017-12-30 15:10 • 来自相关话题

答案是肯定的。
  df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]})
df2 = pd.DataFrame({'A': [6], 'B': [60]})
print 'df\n', df
print 'df2\n', df2输出如下:
df1





df2




 
然后进行合并: df_x = [df, df2]
result = pd.concat(df_x)
print 'first result\n', result
合并后的结果:





 
合并后的index是[0,1,2,3,4,0] 所以index集合是一个类似list的结构,而非set结构,允许重复数据的存在。
 
原文链接:http://30daydo.com/article/256 
转载请注明
 
  查看全部
答案是肯定的。
 
    df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]})
df2 = pd.DataFrame({'A': [6], 'B': [60]})
print 'df\n', df
print 'df2\n', df2
输出如下:
df1
df.PNG


df2
df2.PNG

 
然后进行合并:
    df_x = [df, df2]
result = pd.concat(df_x)
print 'first result\n', result

合并后的结果:

dfx.PNG

 
合并后的index是[0,1,2,3,4,0] 所以index集合是一个类似list的结构,而非set结构,允许重复数据的存在。
 
原文链接:http://30daydo.com/article/256 
转载请注明
 
 

tushare使用get_stock_basic()保存为excel会因为乱码出错而无法保存

李魔佛 发表了文章 • 0 个评论 • 7371 次浏览 • 2017-12-30 13:11 • 来自相关话题

代码如下:
basic=ts.get_stock_basics()

print basic.info()
print basic.head(10)

basic.to_excel('basic2017.xls',encoding='gbk')
运行后会出错:

'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
 
很明显的是编问题。 
 
然后尝试使用解决编码的步骤。
1. reload(sys) 设置default为utf-8: 失败
2. to_excel('stock.xls',encoding='gbk') : 失败,encoding参数换了几个都是失败,utf-8,gb2312,cp1252
 
最后解决的办法是,先把df保存为csv,然后再从csv从读取出来,然后再存储为excel。 整个过程的encoding参数都是用'gbk'.
basic.to_csv('2017_all_price_change.xls',encoding='gbk')
df=pd.read_csv('2017_all_price_change.xls',encoding='gbk')
df.to_excel('2017_all_price_change.xls',encoding='gbk')
  查看全部
代码如下:
    basic=ts.get_stock_basics()

print basic.info()
print basic.head(10)

basic.to_excel('basic2017.xls',encoding='gbk')

运行后会出错:

'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
 
很明显的是编问题。 
 
然后尝试使用解决编码的步骤。
1. reload(sys) 设置default为utf-8: 失败
2. to_excel('stock.xls',encoding='gbk') : 失败,encoding参数换了几个都是失败,utf-8,gb2312,cp1252
 
最后解决的办法是,先把df保存为csv,然后再从csv从读取出来,然后再存储为excel。 整个过程的encoding参数都是用'gbk'.
    basic.to_csv('2017_all_price_change.xls',encoding='gbk')
df=pd.read_csv('2017_all_price_change.xls',encoding='gbk')
df.to_excel('2017_all_price_change.xls',encoding='gbk')

 

pandas to_excel函数参数中的文件名需要为.xls

李魔佛 发表了文章 • 0 个评论 • 11325 次浏览 • 2017-12-29 18:10 • 来自相关话题

例如 df.to_excel('2017-analysis')
会报错。
ValueError: No engine for filetype: ''

需要把文件名也命名为'2017-analysis.xls' 才能过正常运行。
 
不同于其他本文格式,可以随意命名后缀,然后生成文件后再修改后缀。
  查看全部
例如 df.to_excel('2017-analysis')
会报错。
ValueError: No engine for filetype: ''

需要把文件名也命名为'2017-analysis.xls' 才能过正常运行。
 
不同于其他本文格式,可以随意命名后缀,然后生成文件后再修改后缀。
 

Dataframe中的plot函数绘图会把日期index自动补全

李魔佛 发表了文章 • 0 个评论 • 5987 次浏览 • 2017-12-26 14:49 • 来自相关话题

代码如下:
df=pd.read_excel('600050.xls',dtype={'datetime':np.datetime64})
df=df.set_index('datetime')
df['close'].plot(use_index=True,grid=True)
plt.show()
df为中国联通的日线数据,跨度为2016年到2017年底,中间有过一段时间的停牌。 用上面的代码绘制出来的曲线图,回发现,横坐标是日期,可是图中居然会把停牌的日子也插进去,这样导致了图形中间出现了一条长长的折线。
因为停牌后,股价是是不会变化的。 
  查看全部
代码如下:
	df=pd.read_excel('600050.xls',dtype={'datetime':np.datetime64})
df=df.set_index('datetime')
df['close'].plot(use_index=True,grid=True)
plt.show()

df为中国联通的日线数据,跨度为2016年到2017年底,中间有过一段时间的停牌。 用上面的代码绘制出来的曲线图,回发现,横坐标是日期,可是图中居然会把停牌的日子也插进去,这样导致了图形中间出现了一条长长的折线。
因为停牌后,股价是是不会变化的。 
 

pandas dataframe read_excel读取的列设置为日期类型datetime

李魔佛 发表了文章 • 0 个评论 • 22014 次浏览 • 2017-12-25 17:53 • 来自相关话题

比如excel中有一列是日期:





 
如果使用函数 pd.read_excel('xxx.xls') 读入,那么日期列实际会被认为是一个non-null object 类型,虽然可以后期对这个格式进行转换,但其实可以加入一个参数dtype, 就可以在读excel的时候就指定某列的数据类型。
 
pd.read_excel('xxx.xls',dtype={'出生日期':np.datetime64}
 
注意np中的datetime类型是datetime64. 查看全部
比如excel中有一列是日期:

timg.jpg

 
如果使用函数 pd.read_excel('xxx.xls') 读入,那么日期列实际会被认为是一个non-null object 类型,虽然可以后期对这个格式进行转换,但其实可以加入一个参数dtype, 就可以在读excel的时候就指定某列的数据类型。
 
pd.read_excel('xxx.xls',dtype={'出生日期':np.datetime64}
 
注意np中的datetime类型是datetime64.

菜鸟侦探挑战数据分析R源代码

李魔佛 发表了文章 • 0 个评论 • 2933 次浏览 • 2017-12-11 17:45 • 来自相关话题

菜鸟侦探挑战数据分析R源代码:
百度网盘下载链接:
https://pan.baidu.com/s/1miiScDM
 
菜鸟侦探挑战数据分析R源代码:
百度网盘下载链接:
https://pan.baidu.com/s/1miiScDM
 

数字货币量化揭秘-简单暴力但高效的高频交易机器人

littleDream 发表了文章 • 1 个评论 • 6877 次浏览 • 2017-12-05 16:23 • 来自相关话题

策略分享地址:https://www.botvs.com/strategy/1088

这个策略是我做虚拟货币以来的主要策略,后面经过不断完善和修改,复杂了很多,但主要思想并没有改变,分享的这个版本是无明显bug的 最初版本,最为简单清晰,没有仓位管理,每次交易都是满仓,没有卡死后重启等等,但也足够说明问题。

 策略从2014年8月运行,直到今年年初交易所收手续费。期间运行的还算很好,亏损的时间很少。资金从最初的200元跑到了80比特币。具体的过程可以看[小草的新浪博客](小草_新浪博客)里[虚拟货币自动化交易之路](虚拟货币自动化交易之路(五)_小草_新浪博客)系列文章。
 


下图是总资产折合币的曲线:



为什么分享这个策略

1.交易所收取手续费后,几乎杀死了所有的高频策略,我的也不例外。但策略改改也许还能用,大家可以研究一下。

2.好久没有分享东西了,这篇文章早就想写了。

3.和大家共同交流学习。




策略的原理

这个策略原理极为简单,可以理解为准高频的做市策略,各位看了之后可能想打人,这都能赚钱,当时几乎谁都能写出来。我开始也没预料到它能这么有效,可见心中有想法要赶紧付出实践,说不一定有意外之喜。在比特币机器人初兴的2014年,写出赚钱的策略太容易了。

和所有的高频策略一样,本策略也是基于orderbook,下图就是一个典型的比特币交易所的订单分布,



可以看到左侧是买单,显示了不同价格的挂单数量,右侧是卖单。可以想象如果一个人要买入比特币,如果不想挂单等待的话,只能选择吃单,如果他的单子比较多,会使得卖单挂单大量成交,对价格造成冲击,但是这种冲击一般不会一直持续,还有人想吃单卖出,价格在极短时间很可能还会恢复,反过来理解有人要卖币也类似。

以图中的挂单为例,如果要直接买入5个币,那么价格会达到10377,在这时如果有人要直接卖出5个币,价格会达到10348,这个空间就是利润空间.策略会在稍低于10377的价格挂单,如10376.99,同时会以稍高于10348的价格买入,如10348.01,这是如果刚才的情况发生了,显然就会赚到其中的差价。虽然不会每次都如此完美,但在概率的作用下,赚钱的几率实际高得惊人。

以现在策略的参数讲解一下具体操作,这个参数当然无法使用了,仅作一个说明。它会向上寻找累计卖挂单量为8个币的价格,这里是10377,那么此时的卖价就是这个价格减去0.01(减去多少可以是随机的),同理向下寻找累计买挂单为8个币,这里是10348,那么此时的卖价就是10348.01,此时买卖价的差价是10376.99-10348.01=28.98,大于策略预设的差价1.5,就以这两个价格挂单等待成交,如果价差小于1.5,也会找一个价格进行挂单,如盘口价格加减10,等待捡漏(更合适的应该是继续往下找跟多的深度)。




进一步的说明

1. 没有钱或币了怎么办?

这种情况在我的钱较少是十分普遍,大多数时候只挂一边的单子,但不是大问题。其实可以加入币钱平衡的逻辑,但在平衡的过程难免产生损失,毕竟每一次的成交都是概率的垂青,我选择保持单边等待成交,当然这样也浪费了另一边的成交机会。

2. 仓位是如何管理的?

刚开始都是满仓买入卖出,后来根据不同的参数分为不同的组,不会一次完全成交。

3. 没有止损吗?

策略有完整的买卖挂单的逻辑,我认为不需要止损(可以讨论),还有就是概率的垂青,成交就是机会,止损可惜了。

4. 如何调整为赚币的策略?

此时的参数是对称的,即向上8个币的累计卖单,向下8个币的累计买单,稍微不平衡一下,比如向上改为15个币的累计卖单,使得卖币机会更难得,有更大的几率会以更低的价格接回来,这样就会赚币,反过来就赚钱。实际上前期策略如此有效,币和钱都是增加的。




代码讲解

完整的代码可以见我在http://www.botvs.com得策略分享,这里只讲解核心逻辑函数。在没有改动的情况下,在botvs自带的模拟盘竟然运转完全正常,这是一个3年多前的策略,平台还支持到现在,太让人感动了。

首先是获取买卖价函数GetPrice(),需要获取订单深度信息,注意不同平台的订单深度信息长度不同,以及即使遍历了所有订单仍然没有所需要的量的情况(在后期许多0.01的网格挂单会导致这种情况),调用是GetPrice('Buy')就是获取买价。
 
function GetPrice(Type) {
//_C()是平台的容错函数
var depth=_C(exchange.GetDepth);
var amountBids=0;
var amountAsks=0;
//计算买价,获取累计深度达到预设的价格
if(Type=="Buy"){
for(var i=0;i<20;i++){
amountBids+=depth.Bids[i].Amount;
//参数floatamountbuy是预设的累计深度
if (amountBids>floatamountbuy){
//稍微加0.01,使得订单排在前面
return depth.Bids[i].Price+0.01;}
}
}
//同理计算卖价
if(Type=="Sell"){
for(var j=0; j<20; j++){
amountAsks+=depth.Asks[j].Amount;
if (amountAsks>floatamountsell){
return depth.Asks[j].Price-0.01;}
}
}
//遍历了全部深度仍未满足需求,就返回一个价格,以免出现bug
return depth.Asks[0].Price
}

// 每个循环的主函数onTick(),这里定的循环时间3.5s,每次循环都会把原来的单子撤销,重新挂单,越简单越不会遇到bug.

function onTick() {
var buyPrice = GetPrice("Buy");
var sellPrice= GetPrice("Sell");
//diffprice是预设差价,买卖价差如果小于预设差价,就会挂一个相对更深的价格
if ((sellPrice - buyPrice) <= diffprice){
buyPrice-=10;
sellPrice+=10;}
//把原有的单子全部撤销,实际上经常出现新的价格和已挂单价格相同的情况,此时不需要撤销
CancelPendingOrders()
//获取账户信息,确定目前账户存在多少钱和多少币
var account=_C(exchange.GetAccount);
//可买的比特币量,_N()是平台的精度函数
var amountBuy = _N((account.Balance / buyPrice-0.1),2);
//可卖的比特币量,注意到没有仓位的限制,有多少就买卖多少,因为我当时的钱很少
var amountSell = _N((account.Stocks),2);
if (amountSell > 0.02) {
exchange.Sell(sellPrice,amountSell);}
if (amountBuy > 0.02) {
exchange.Buy(buyPrice, amountBuy);}
//休眠,进入下一轮循环
Sleep(sleeptime);
}


尾巴

整个程序也就40多行,看上去十分简单,但当时也花了我一个多星期,这还是在botvs平台上情况下。最大的优势还是起步早,在2014年,市场上以搬砖为主,网格和抢盘口的高频也不多,使得策略如鱼得水,后来竞争不可避免越来越激烈,我的钱也越来越多,面临的挑战很多,每隔一段时间都要进行较大的改动来应对,但总体还算顺利。在交易平台不收取手续费的情况下,是程序化交易的天堂,散户因为不收手续费跟倾向于操作,为高频和套利提供了空间,这一切也基本随着动辄0.1-0.2%的双向手续费终结了,不仅是自己被收费的问题,而是整个市场活跃度下降。

但不需要高频的量化策略任然有很大的空间。

作者 小草 查看全部
策略分享地址:https://www.botvs.com/strategy/1088


这个策略是我做虚拟货币以来的主要策略,后面经过不断完善和修改,复杂了很多,但主要思想并没有改变,分享的这个版本是无明显bug的 最初版本,最为简单清晰,没有仓位管理,每次交易都是满仓,没有卡死后重启等等,但也足够说明问题。


 策略从2014年8月运行,直到今年年初交易所收手续费。期间运行的还算很好,亏损的时间很少。资金从最初的200元跑到了80比特币。具体的过程可以看[小草的新浪博客](小草_新浪博客)里[虚拟货币自动化交易之路](虚拟货币自动化交易之路(五)_小草_新浪博客)系列文章。
 


下图是总资产折合币的曲线:



为什么分享这个策略

1.交易所收取手续费后,几乎杀死了所有的高频策略,我的也不例外。但策略改改也许还能用,大家可以研究一下。

2.好久没有分享东西了,这篇文章早就想写了。

3.和大家共同交流学习。




策略的原理

这个策略原理极为简单,可以理解为准高频的做市策略,各位看了之后可能想打人,这都能赚钱,当时几乎谁都能写出来。我开始也没预料到它能这么有效,可见心中有想法要赶紧付出实践,说不一定有意外之喜。在比特币机器人初兴的2014年,写出赚钱的策略太容易了。

和所有的高频策略一样,本策略也是基于orderbook,下图就是一个典型的比特币交易所的订单分布,



可以看到左侧是买单,显示了不同价格的挂单数量,右侧是卖单。可以想象如果一个人要买入比特币,如果不想挂单等待的话,只能选择吃单,如果他的单子比较多,会使得卖单挂单大量成交,对价格造成冲击,但是这种冲击一般不会一直持续,还有人想吃单卖出,价格在极短时间很可能还会恢复,反过来理解有人要卖币也类似。

以图中的挂单为例,如果要直接买入5个币,那么价格会达到10377,在这时如果有人要直接卖出5个币,价格会达到10348,这个空间就是利润空间.策略会在稍低于10377的价格挂单,如10376.99,同时会以稍高于10348的价格买入,如10348.01,这是如果刚才的情况发生了,显然就会赚到其中的差价。虽然不会每次都如此完美,但在概率的作用下,赚钱的几率实际高得惊人。

以现在策略的参数讲解一下具体操作,这个参数当然无法使用了,仅作一个说明。它会向上寻找累计卖挂单量为8个币的价格,这里是10377,那么此时的卖价就是这个价格减去0.01(减去多少可以是随机的),同理向下寻找累计买挂单为8个币,这里是10348,那么此时的卖价就是10348.01,此时买卖价的差价是10376.99-10348.01=28.98,大于策略预设的差价1.5,就以这两个价格挂单等待成交,如果价差小于1.5,也会找一个价格进行挂单,如盘口价格加减10,等待捡漏(更合适的应该是继续往下找跟多的深度)。




进一步的说明

1. 没有钱或币了怎么办?

这种情况在我的钱较少是十分普遍,大多数时候只挂一边的单子,但不是大问题。其实可以加入币钱平衡的逻辑,但在平衡的过程难免产生损失,毕竟每一次的成交都是概率的垂青,我选择保持单边等待成交,当然这样也浪费了另一边的成交机会。

2. 仓位是如何管理的?

刚开始都是满仓买入卖出,后来根据不同的参数分为不同的组,不会一次完全成交。

3. 没有止损吗?

策略有完整的买卖挂单的逻辑,我认为不需要止损(可以讨论),还有就是概率的垂青,成交就是机会,止损可惜了。

4. 如何调整为赚币的策略?

此时的参数是对称的,即向上8个币的累计卖单,向下8个币的累计买单,稍微不平衡一下,比如向上改为15个币的累计卖单,使得卖币机会更难得,有更大的几率会以更低的价格接回来,这样就会赚币,反过来就赚钱。实际上前期策略如此有效,币和钱都是增加的。




代码讲解

完整的代码可以见我在http://www.botvs.com得策略分享,这里只讲解核心逻辑函数。在没有改动的情况下,在botvs自带的模拟盘竟然运转完全正常,这是一个3年多前的策略,平台还支持到现在,太让人感动了。

首先是获取买卖价函数GetPrice(),需要获取订单深度信息,注意不同平台的订单深度信息长度不同,以及即使遍历了所有订单仍然没有所需要的量的情况(在后期许多0.01的网格挂单会导致这种情况),调用是GetPrice('Buy')就是获取买价。
 
function GetPrice(Type) {
//_C()是平台的容错函数
var depth=_C(exchange.GetDepth);
var amountBids=0;
var amountAsks=0;
//计算买价,获取累计深度达到预设的价格
if(Type=="Buy"){
for(var i=0;i<20;i++){
amountBids+=depth.Bids[i].Amount;
//参数floatamountbuy是预设的累计深度
if (amountBids>floatamountbuy){
//稍微加0.01,使得订单排在前面
return depth.Bids[i].Price+0.01;}
}
}
//同理计算卖价
if(Type=="Sell"){
for(var j=0; j<20; j++){
amountAsks+=depth.Asks[j].Amount;
if (amountAsks>floatamountsell){
return depth.Asks[j].Price-0.01;}
}
}
//遍历了全部深度仍未满足需求,就返回一个价格,以免出现bug
return depth.Asks[0].Price
}

// 每个循环的主函数onTick(),这里定的循环时间3.5s,每次循环都会把原来的单子撤销,重新挂单,越简单越不会遇到bug.

function onTick() {
var buyPrice = GetPrice("Buy");
var sellPrice= GetPrice("Sell");
//diffprice是预设差价,买卖价差如果小于预设差价,就会挂一个相对更深的价格
if ((sellPrice - buyPrice) <= diffprice){
buyPrice-=10;
sellPrice+=10;}
//把原有的单子全部撤销,实际上经常出现新的价格和已挂单价格相同的情况,此时不需要撤销
CancelPendingOrders()
//获取账户信息,确定目前账户存在多少钱和多少币
var account=_C(exchange.GetAccount);
//可买的比特币量,_N()是平台的精度函数
var amountBuy = _N((account.Balance / buyPrice-0.1),2);
//可卖的比特币量,注意到没有仓位的限制,有多少就买卖多少,因为我当时的钱很少
var amountSell = _N((account.Stocks),2);
if (amountSell > 0.02) {
exchange.Sell(sellPrice,amountSell);}
if (amountBuy > 0.02) {
exchange.Buy(buyPrice, amountBuy);}
//休眠,进入下一轮循环
Sleep(sleeptime);
}



尾巴

整个程序也就40多行,看上去十分简单,但当时也花了我一个多星期,这还是在botvs平台上情况下。最大的优势还是起步早,在2014年,市场上以搬砖为主,网格和抢盘口的高频也不多,使得策略如鱼得水,后来竞争不可避免越来越激烈,我的钱也越来越多,面临的挑战很多,每隔一段时间都要进行较大的改动来应对,但总体还算顺利。在交易平台不收取手续费的情况下,是程序化交易的天堂,散户因为不收手续费跟倾向于操作,为高频和套利提供了空间,这一切也基本随着动辄0.1-0.2%的双向手续费终结了,不仅是自己被收费的问题,而是整个市场活跃度下降。

但不需要高频的量化策略任然有很大的空间。

作者 小草

TypeError: reduction operation 'argmin' not allowed for this dtype

李魔佛 发表了文章 • 0 个评论 • 11343 次浏览 • 2017-11-19 18:48 • 来自相关话题

使用pd.read_sql() 方法把Mysql的数据库转为dataframe后,使用 df['low'].idxmin() 或者df['low'].argmin() 方法是会出现这个错误。
 
date = date + '-01-01'
cmd = 'select * from `{}` where datetime > \'{}\''.format(code, date)

try:
df = pd.read_sql(cmd, history_engine,index_col='index')
except Exception,e:
print e
return None

# 不知道为啥,这里的类型发生改变
idx= df['low'].idxmin() 
 
TypeError: reduction operation 'argmin' not allowed for this dtype
 
把df的每列数据类型打印出来看看。
 
print df.dtypes
 
datetime datetime64[ns]
code object
name object
open object
close object
high object
low object
vol float64
amount float64
dtype: object
晕,居然把low这些float类型全部转为了object,所以解决办法就是把这些列的数据转为float64.
 
df['low']=df['low'].astype('float64')
这样之后,问题就解决了。
  查看全部
使用pd.read_sql() 方法把Mysql的数据库转为dataframe后,使用 df['low'].idxmin() 或者df['low'].argmin() 方法是会出现这个错误。
 
date = date + '-01-01'
cmd = 'select * from `{}` where datetime > \'{}\''.format(code, date)

try:
df = pd.read_sql(cmd, history_engine,index_col='index')
except Exception,e:
print e
return None

# 不知道为啥,这里的类型发生改变
idx= df['low'].idxmin()
 
 
TypeError: reduction operation 'argmin' not allowed for this dtype
 
把df的每列数据类型打印出来看看。
 
print df.dtypes
 
datetime    datetime64[ns]
code object
name object
open object
close object
high object
low object
vol float64
amount float64
dtype: object

晕,居然把low这些float类型全部转为了object,所以解决办法就是把这些列的数据转为float64.
 
df['low']=df['low'].astype('float64')

这样之后,问题就解决了。
 

监控聚币网行情 并实时发送到微信

李魔佛 发表了文章 • 1 个评论 • 7848 次浏览 • 2017-05-29 17:38 • 来自相关话题

最近由于好友推荐我入坑了国内的山寨币,所以顺便研究了下聚币网的API。 不过网页版的聚币网和手机版的做的不好,而且因为是7x24 小时交易,自己没有那么多的精力盯盘,所以写了python代码进行监控。




# -*-coding=utf-8-*-
__author__ = 'Rocky'
'''
http://30daydo.com
Contact: weigesysu@qq.com
'''
import random
import hashlib
import hmac,time
import smtplib
from email.mime.text import MIMEText
from email import Utils
import threading
import requests,datetime,itchat

from toolkit import Toolkit


class Jubi_web():
def __init__(self, send=None):
cfg = Toolkit.getUserData('data.cfg')
self.public_key = cfg['public_key']
self.private_key = cfg['private_key']
self.send=send
from_mail = cfg['from_mail']
password = cfg['password']
to_mail = cfg['to_mail']
smtp_server = 'smtp.qq.com'

self.server = smtp_server
self.username = from_mail.split("@")[0]
self.from_mail = from_mail
self.password = password
self.to_mail = to_mail
self.coin_list=['IFC','DOGE','EAC','DNC','MET','ZET','SKT','YTC','PLC','LKC',
'JBC','MRYC','GOOC','QEC','PEB','XRP','NXT','WDC','MAX','ZCC',
'HLB','RSS','PGC','RIO','XAS','TFC','BLK','FZ','ANS','XPM','VTC',
'KTC','VRC','XSGS','LSK','PPC','ETC','GAME','LTC','ETH','BTC']
# 初始化邮箱设置读取需要股票信息
# 这样子只登陆一次
if self.send == 'msn':

try:
self.smtp = smtplib.SMTP_SSL(port=465)
self.smtp.connect(self.server)
self.smtp.login(self.username, self.password)
except smtplib.SMTPException, e:
print e
return 0

if send=='wechat':
self.w_name=u'xxxxx'

itchat.auto_login(hotReload=True)
account=itchat.get_friends(self.w_name)


def send_wechat(self,name,content):
w_content=name+' '+content
itchat.send(w_content,toUserName=self.toName)
time.sleep(1)
itchat.send(w_content,toUserName='filehelper')


def send_text(self, name, content):

subject = '%s' % name
self.msg = MIMEText(content, 'plain', 'utf-8')
self.msg['to'] = self.to_mail
self.msg['from'] = self.from_mail
self.msg['Subject'] = subject
self.msg['Date'] = Utils.formatdate(localtime=1)
try:
self.smtp.sendmail(self.msg['from'], self.msg['to'], self.msg.as_string())
self.smtp.quit()
print "sent"
except smtplib.SMTPException, e:
print e
return 0

def warming(self, coin, up_price, down_price):
url = 'https://www.jubi.com/api/v1/ticker/'
while 1:
time.sleep(5)
try:
data = requests.post(url, data={'coin': coin}).json()
except Exception,e:
print e
print "time out. Retry"
time.sleep(15)
continue

current = float(data['last'])
if current >= up_price:
print "Up to ", up_price
print "current price ",current

if self.send=='msn':
self.send_text(coin,str(current))
if self.send=='wechat':
self.send_wechat(coin,str(current))

time.sleep(1200)
if current <= down_price:
print "Down to ", down_price
print "current price ",current
if self.send=='msn':
self.send_text(coin,str(current))
if self.send=='wechat':
self.send_wechat(coin,str(current))
time.sleep(1200)
#上面的内容尽量不用修改。


def getContent(self):
url = 'https://www.jubi.com/api/v1/trade_list'
params_data = {'key': 'x', 'signature': 'x'}
s = requests.get(url=url, params=params_data)

def getHash(self, s):
m = hashlib.md5()
m.update(s)
return m.hexdigest()

def sha_convert(self, s):
return hashlib.sha256(self.getHash(s)).hexdigest()

def get_nonce(self):
lens = 12
return ''.join([str(random.randint(0, 9)) for i in range(lens)])

def get_signiture(self):
url = 'xxxxxxxxx'
coin = 'zet'
nonce = self.get_nonce()

# sha=self.sha_convert(private_key)
md5 = self.getHash(self.private_key)
message = 'nonce=' + nonce + '&' + 'key=' + self.public_key
# print message
signature = hmac.new(md5, message, digestmod=hashlib.sha256).digest()
# print signature

# req=requests.post(url,data={'signature':signature,'key':public_key,'nonce':nonce,'coin':'zet'})
req = requests.post(url, data={'coin': coin})
print req.status_code
print req.text

def real_time_ticker(self, coin):
url = 'xxxxxxxx'
try:
data = requests.post(url, data={'coin': coin}).json()
#print data
except Exception ,e:
print e
return data


def real_time_depth(self, coin):
url = 'xxxxxxxxx'
data = requests.post(url, data={'coin': coin}).json()
print data
data_bids = data['bids']
data_asks = data['asks']
print "bids"
for i in data_bids:
print i[0],
print ' ',
print i[1]
print "asks"
for j in data_asks:
print j[0],
print ' ',
print j[1]

def list_all_price(self):
for i in self.coin_list:
print i,
print " price: ",
p=self.real_time_ticker(i.lower())
if p is not None:
print p[u'last']

def getOrder(self,coin):
url='https://www.jubi.com/api/v1/orders/'
try:
req=requests.get(url,params={'coin':coin})
except Exception,e:
print e

data=req.json()
return data
# recent 100 trade turn over
def turnover(self,coin):
i=coin.lower()
coins=Toolkit.getUserData('coins.csv')
total=long(coins[i])
[i] [/i]p=self.getOrder(i)
print p
amount=0.00
for j in p:
t= j[u'amount']
amount=float(t)+amount
#current=float(self.real_time_ticker(i)[u'last'])
turn_over=amount*1.00/total*100
print turn_over

def multi_thread(self,coin_list,price_list):
thread_num=len(coin_list)
thread_list=
for i in range(thread_num):
t=threading.Thread(target=self.warming, args=(coin_list,price_list[0],price_list[1]),)
thread_list.append(t)
for j in thread_list:
j.start()
for k in thread_list:
k.join()

if __name__ == '__main__':

obj = Jubi_web(send='wechat')
coin_list=['zet','doge']
price_list=[[0.2,0.13],[0.03,0.024]]
obj.multi_thread(coin_list,price_list)

[/i]
程序运行后,使用扫一扫登录。 

coin_list=['zet','doge'] price_list=[[0.2,0.13],[0.03,0.024]]
 
通过这个参数,设置你想要监控的币种和目标价格。
同时程序支持发送给多个用户。
 

 http://30daydo.com/article/205
转载请注明出处 查看全部
最近由于好友推荐我入坑了国内的山寨币,所以顺便研究了下聚币网的API。 不过网页版的聚币网和手机版的做的不好,而且因为是7x24 小时交易,自己没有那么多的精力盯盘,所以写了python代码进行监控。

Screenshot_2017-05-29-23-02-13-420_微信_副本_副本.png
# -*-coding=utf-8-*-
__author__ = 'Rocky'
'''
http://30daydo.com
Contact: weigesysu@qq.com
'''
import random
import hashlib
import hmac,time
import smtplib
from email.mime.text import MIMEText
from email import Utils
import threading
import requests,datetime,itchat

from toolkit import Toolkit


class Jubi_web():
def __init__(self, send=None):
cfg = Toolkit.getUserData('data.cfg')
self.public_key = cfg['public_key']
self.private_key = cfg['private_key']
self.send=send
from_mail = cfg['from_mail']
password = cfg['password']
to_mail = cfg['to_mail']
smtp_server = 'smtp.qq.com'

self.server = smtp_server
self.username = from_mail.split("@")[0]
self.from_mail = from_mail
self.password = password
self.to_mail = to_mail
self.coin_list=['IFC','DOGE','EAC','DNC','MET','ZET','SKT','YTC','PLC','LKC',
'JBC','MRYC','GOOC','QEC','PEB','XRP','NXT','WDC','MAX','ZCC',
'HLB','RSS','PGC','RIO','XAS','TFC','BLK','FZ','ANS','XPM','VTC',
'KTC','VRC','XSGS','LSK','PPC','ETC','GAME','LTC','ETH','BTC']
# 初始化邮箱设置读取需要股票信息
# 这样子只登陆一次
if self.send == 'msn':

try:
self.smtp = smtplib.SMTP_SSL(port=465)
self.smtp.connect(self.server)
self.smtp.login(self.username, self.password)
except smtplib.SMTPException, e:
print e
return 0

if send=='wechat':
self.w_name=u'xxxxx'

itchat.auto_login(hotReload=True)
account=itchat.get_friends(self.w_name)


def send_wechat(self,name,content):
w_content=name+' '+content
itchat.send(w_content,toUserName=self.toName)
time.sleep(1)
itchat.send(w_content,toUserName='filehelper')


def send_text(self, name, content):

subject = '%s' % name
self.msg = MIMEText(content, 'plain', 'utf-8')
self.msg['to'] = self.to_mail
self.msg['from'] = self.from_mail
self.msg['Subject'] = subject
self.msg['Date'] = Utils.formatdate(localtime=1)
try:
self.smtp.sendmail(self.msg['from'], self.msg['to'], self.msg.as_string())
self.smtp.quit()
print "sent"
except smtplib.SMTPException, e:
print e
return 0

def warming(self, coin, up_price, down_price):
url = 'https://www.jubi.com/api/v1/ticker/'
while 1:
time.sleep(5)
try:
data = requests.post(url, data={'coin': coin}).json()
except Exception,e:
print e
print "time out. Retry"
time.sleep(15)
continue

current = float(data['last'])
if current >= up_price:
print "Up to ", up_price
print "current price ",current

if self.send=='msn':
self.send_text(coin,str(current))
if self.send=='wechat':
self.send_wechat(coin,str(current))

time.sleep(1200)
if current <= down_price:
print "Down to ", down_price
print "current price ",current
if self.send=='msn':
self.send_text(coin,str(current))
if self.send=='wechat':
self.send_wechat(coin,str(current))
time.sleep(1200)
#上面的内容尽量不用修改。


def getContent(self):
url = 'https://www.jubi.com/api/v1/trade_list'
params_data = {'key': 'x', 'signature': 'x'}
s = requests.get(url=url, params=params_data)

def getHash(self, s):
m = hashlib.md5()
m.update(s)
return m.hexdigest()

def sha_convert(self, s):
return hashlib.sha256(self.getHash(s)).hexdigest()

def get_nonce(self):
lens = 12
return ''.join([str(random.randint(0, 9)) for i in range(lens)])

def get_signiture(self):
url = 'xxxxxxxxx'
coin = 'zet'
nonce = self.get_nonce()

# sha=self.sha_convert(private_key)
md5 = self.getHash(self.private_key)
message = 'nonce=' + nonce + '&' + 'key=' + self.public_key
# print message
signature = hmac.new(md5, message, digestmod=hashlib.sha256).digest()
# print signature

# req=requests.post(url,data={'signature':signature,'key':public_key,'nonce':nonce,'coin':'zet'})
req = requests.post(url, data={'coin': coin})
print req.status_code
print req.text

def real_time_ticker(self, coin):
url = 'xxxxxxxx'
try:
data = requests.post(url, data={'coin': coin}).json()
#print data
except Exception ,e:
print e
return data


def real_time_depth(self, coin):
url = 'xxxxxxxxx'
data = requests.post(url, data={'coin': coin}).json()
print data
data_bids = data['bids']
data_asks = data['asks']
print "bids"
for i in data_bids:
print i[0],
print ' ',
print i[1]
print "asks"
for j in data_asks:
print j[0],
print ' ',
print j[1]

def list_all_price(self):
for i in self.coin_list:
print i,
print " price: ",
p=self.real_time_ticker(i.lower())
if p is not None:
print p[u'last']

def getOrder(self,coin):
url='https://www.jubi.com/api/v1/orders/'
try:
req=requests.get(url,params={'coin':coin})
except Exception,e:
print e

data=req.json()
return data
# recent 100 trade turn over
def turnover(self,coin):
i=coin.lower()
coins=Toolkit.getUserData('coins.csv')
total=long(coins[i])
[i] [/i]p=self.getOrder(i)
print p
amount=0.00
for j in p:
t= j[u'amount']
amount=float(t)+amount
#current=float(self.real_time_ticker(i)[u'last'])
turn_over=amount*1.00/total*100
print turn_over

def multi_thread(self,coin_list,price_list):
thread_num=len(coin_list)
thread_list=
for i in range(thread_num):
t=threading.Thread(target=self.warming, args=(coin_list,price_list[0],price_list[1]),)
thread_list.append(t)
for j in thread_list:
j.start()
for k in thread_list:
k.join()

if __name__ == '__main__':

obj = Jubi_web(send='wechat')
coin_list=['zet','doge']
price_list=[[0.2,0.13],[0.03,0.024]]
obj.multi_thread(coin_list,price_list)

[/i]

程序运行后,使用扫一扫登录。 

coin_list=['zet','doge'] price_list=[[0.2,0.13],[0.03,0.024]]
 
通过这个参数,设置你想要监控的币种和目标价格。
同时程序支持发送给多个用户。
 

 http://30daydo.com/article/205
转载请注明出处

TA-Lib中MOM的计算公式

李魔佛 发表了文章 • 0 个评论 • 6990 次浏览 • 2017-05-29 01:38 • 来自相关话题

MOM是价格动能。
 TA-Lib中MOM的参数有
ouput=talib.MOM(closed,timeperiod=5)
 
closed是你传入的价格list,可以是每天的收盘价,开盘价,或者你想要计算的所有价格。
timeperiod是你要计算的时间周期。
 
假如timeperiod=5,那么,这个计算的输出值就是 p5-p0, 如果今天是1月6日,股价为14块,而1月1日的股价为12块,那么这里通过MOM运算,得出来的就是14-12=2 这个值了。 然后如此类推,如果今天是1月7日,股价为15块,而1月2日股价为11块,那么MOM得出的是4,这样子获取到所有的值,绘制成曲线,就是MOM的曲线了。 查看全部
MOM是价格动能。
 TA-Lib中MOM的参数有
ouput=talib.MOM(closed,timeperiod=5)
 
closed是你传入的价格list,可以是每天的收盘价,开盘价,或者你想要计算的所有价格。
timeperiod是你要计算的时间周期。
 
假如timeperiod=5,那么,这个计算的输出值就是 p5-p0, 如果今天是1月6日,股价为14块,而1月1日的股价为12块,那么这里通过MOM运算,得出来的就是14-12=2 这个值了。 然后如此类推,如果今天是1月7日,股价为15块,而1月2日股价为11块,那么MOM得出的是4,这样子获取到所有的值,绘制成曲线,就是MOM的曲线了。

TA-Lib 量化交易代码实例 <二> 获取布林线的上轨,中轨,下轨的数据

李魔佛 发表了文章 • 0 个评论 • 24413 次浏览 • 2017-05-28 23:08 • 来自相关话题

BOLL指标的原理
BOLL指标是美国股市分析家约翰·布林根据统计学中的标准差原理设计出来的一种非常简单实用的技术分析指标。一般而言,股价的运动总是围绕某一价值中枢(如均线、成本线等)在一定的范围内变动,布林线指标指标正是在上述条件的基础上,引进了“股价通道”的概念,其认为股价通道的宽窄随着股价波动幅度的大小而变化,而且股价通道又具有变异性,它会随着股价的变化而自动调整。正是由于它具有灵活性、直观性和趋势性的特点,BOLL指标渐渐成为投资者广为应用的市场上热门指标。
在众多技术分析指标中,BOLL指标属于比较特殊的一类指标。绝大多数技术分析指标都是通过数量的方法构造出来的,它们本身不依赖趋势分析和形态分析,而BOLL指标却股价的形态和趋势有着密不可分的联系。BOLL指标中的“股价通道”概念正是股价趋势理论的直观表现形式。BOLL是利用“股价通道”来显示股价的各种价位,当股价波动很小,处于盘整时,股价通道就会变窄,这可能预示着股价的波动处于暂时的平静期;当股价波动超出狭窄的股价通道的上轨时,预示着股价的异常激烈的向上波动即将开始;当股价波动超出狭窄的股价通道的下轨时,同样也预示着股价的异常激烈的向下波动将开始。
投资者常常会遇到两种最常见的交易陷阱,一是买低陷阱,投资者在所谓的低位买进之后,股价不仅没有止跌反而不断下跌;二是卖高陷阱,股票在所谓的高点卖出后,股价却一路上涨。布林线特别运用了爱因斯坦的相对论,认为各类市场间都是互动的,市场内和市场间的各种变化都是相对性的,是不存在绝对性的,股价的高低是相对的,股价在上轨线以上或在下轨线以下只反映该股股价相对较高或较低,投资者作出投资判断前还须综合参考其他技术指标,包括价量配合,心理类指标,类比类指标,市场间的关联数据等。
总之,BOLL指标中的股价通道对预测未来行情的走势起着重要的参考作用,它也是布林线指标所特有的分析手段。
[编辑]
BOLL指标的计算方法
在所有的指标计算中,BOLL指标的计算方法是最复杂的之一,其中引进了统计学中的标准差概念,涉及到中轨线(MB)、上轨线(UP)和下轨线(DN)的计算。另外,和其他指标的计算一样,由于选用的计算周期的不同,BOLL指标也包括日BOLL指标、周BOLL指标、月BOLL指标年BOLL指标以及分钟BOLL指标等各种类型。经常被用于股市研判的是日BOLL指标和周BOLL指标。虽然它们的计算时的取值有所不同,但基本的计算方法一样。以日BOLL指标计算为例,其计算方法如下:
1、日BOLL指标的计算公式
中轨线=N日的移动平均线
上轨线=中轨线+两倍的标准差
下轨线=中轨线-两倍的标准差
2、日BOLL指标的计算过程
1)计算MA
MA=N日内的收盘价之和÷N2)计算标准差MD
MD=平方根N日的(C-MA)的两次方之和除以N3)计算MB、UP、DN线
MB=(N-1)日的MA
UP=MB+2×MD
DN=MB-2×MD在股市分析软件中,BOLL指标一共由四条线组成,即上轨线UP 、中轨线MB、下轨线DN和价格线。其中上轨线UP是UP数值的连线,用黄色线表示;中轨线MB是MB数值的连线,用白色线表示;下轨线DN是DN数值的连线,用紫色线表示;价格线是以美国线表示,颜色为浅蓝色。和其他技术指标一样,在实战中,投资者不需要进行BOLL指标的计算,主要是了解BOLL的计算方法和过程,以便更加深入地掌握BOLL指标的实质,为运用指标打下基础。
 
#通过tushare获取股票信息
df=ts.get_k_data('300580',start='2017-01-12',end='2017-05-26')
#提取收盘价
closed=df['close'].values

upper,middle,lower=talib.BBANDS(closed,matype=talib.MA_Type.T3)

print upper,middle,lower
plt.plot(upper)
plt.plot(middle)
plt.plot(lower)
plt.grid()
plt.show()
diff1=upper-middle
diff2=middle-lower
print diff1
print diff2





 
最后那里可以看到diff1和diff2是一样的。 验证了布林线的定义ma+2d,m-2d。 查看全部

BOLL指标的原理
BOLL指标是美国股市分析家约翰·布林根据统计学中的标准差原理设计出来的一种非常简单实用的技术分析指标。一般而言,股价的运动总是围绕某一价值中枢(如均线、成本线等)在一定的范围内变动,布林线指标指标正是在上述条件的基础上,引进了“股价通道”的概念,其认为股价通道的宽窄随着股价波动幅度的大小而变化,而且股价通道又具有变异性,它会随着股价的变化而自动调整。正是由于它具有灵活性、直观性和趋势性的特点,BOLL指标渐渐成为投资者广为应用的市场上热门指标。
在众多技术分析指标中,BOLL指标属于比较特殊的一类指标。绝大多数技术分析指标都是通过数量的方法构造出来的,它们本身不依赖趋势分析和形态分析,而BOLL指标却股价的形态和趋势有着密不可分的联系。BOLL指标中的“股价通道”概念正是股价趋势理论的直观表现形式。BOLL是利用“股价通道”来显示股价的各种价位,当股价波动很小,处于盘整时,股价通道就会变窄,这可能预示着股价的波动处于暂时的平静期;当股价波动超出狭窄的股价通道的上轨时,预示着股价的异常激烈的向上波动即将开始;当股价波动超出狭窄的股价通道的下轨时,同样也预示着股价的异常激烈的向下波动将开始。
投资者常常会遇到两种最常见的交易陷阱,一是买低陷阱,投资者在所谓的低位买进之后,股价不仅没有止跌反而不断下跌;二是卖高陷阱,股票在所谓的高点卖出后,股价却一路上涨。布林线特别运用了爱因斯坦的相对论,认为各类市场间都是互动的,市场内和市场间的各种变化都是相对性的,是不存在绝对性的,股价的高低是相对的,股价在上轨线以上或在下轨线以下只反映该股股价相对较高或较低,投资者作出投资判断前还须综合参考其他技术指标,包括价量配合,心理类指标,类比类指标,市场间的关联数据等。
总之,BOLL指标中的股价通道对预测未来行情的走势起着重要的参考作用,它也是布林线指标所特有的分析手段。
[编辑]
BOLL指标的计算方法
在所有的指标计算中,BOLL指标的计算方法是最复杂的之一,其中引进了统计学中的标准差概念,涉及到中轨线(MB)、上轨线(UP)和下轨线(DN)的计算。另外,和其他指标的计算一样,由于选用的计算周期的不同,BOLL指标也包括日BOLL指标、周BOLL指标、月BOLL指标年BOLL指标以及分钟BOLL指标等各种类型。经常被用于股市研判的是日BOLL指标和周BOLL指标。虽然它们的计算时的取值有所不同,但基本的计算方法一样。以日BOLL指标计算为例,其计算方法如下:
1、日BOLL指标的计算公式
中轨线=N日的移动平均线
上轨线=中轨线+两倍的标准差
下轨线=中轨线-两倍的标准差
2、日BOLL指标的计算过程
1)计算MA
MA=N日内的收盘价之和÷N2)计算标准差MD
MD=平方根N日的(C-MA)的两次方之和除以N3)计算MB、UP、DN线
MB=(N-1)日的MA
UP=MB+2×MD
DN=MB-2×MD在股市分析软件中,BOLL指标一共由四条线组成,即上轨线UP 、中轨线MB、下轨线DN和价格线。其中上轨线UP是UP数值的连线,用黄色线表示;中轨线MB是MB数值的连线,用白色线表示;下轨线DN是DN数值的连线,用紫色线表示;价格线是以美国线表示,颜色为浅蓝色。和其他技术指标一样,在实战中,投资者不需要进行BOLL指标的计算,主要是了解BOLL的计算方法和过程,以便更加深入地掌握BOLL指标的实质,为运用指标打下基础。
 
    #通过tushare获取股票信息
df=ts.get_k_data('300580',start='2017-01-12',end='2017-05-26')
#提取收盘价
closed=df['close'].values

upper,middle,lower=talib.BBANDS(closed,matype=talib.MA_Type.T3)

print upper,middle,lower
plt.plot(upper)
plt.plot(middle)
plt.plot(lower)
plt.grid()
plt.show()
diff1=upper-middle
diff2=middle-lower
print diff1
print diff2


布林线.PNG

 
最后那里可以看到diff1和diff2是一样的。 验证了布林线的定义ma+2d,m-2d。

quantdigger 量化交易入门 代码示例

李魔佛 发表了文章 • 1 个评论 • 4541 次浏览 • 2017-05-28 21:39 • 来自相关话题

第五天
 
《》
待更新
第五天
 
《》
待更新

TA-Lib 量化交易代码实例 <一> 获取5日,10日,20日均线数据

李魔佛 发表了文章 • 0 个评论 • 23980 次浏览 • 2017-05-28 21:37 • 来自相关话题

第一节
 
安装教程在前面内容已经介绍过了,对于新手也是有点障碍,可以参照前面的文章进行一步一步操作。 http://30daydo.com/article/195 #通过tushare获取股票信息
df=ts.get_k_data('300580',start='2017-01-12',end='2017-05-26')
#提取收盘价
closed=df['close'].values
#获取均线的数据,通过timeperiod参数来分别获取 5,10,20 日均线的数据。
ma5=talib.SMA(closed,timeperiod=5)
ma10=talib.SMA(closed,timeperiod=10)
ma20=talib.SMA(closed,timeperiod=20)

#打印出来每一个数据
print closed
print ma5
print ma10
print ma20

#通过plog函数可以很方便的绘制出每一条均线
plt.plot(closed)
plt.plot(ma5)
plt.plot(ma10)
plt.plot(ma20)
#添加网格,可有可无,只是让图像好看点
plt.grid()
#记得加这一句,不然不会显示图像
plt.show()
上面第一句使用tushare获取股票的数据,如果不知道怎么操作的,可以在这里参考,同样是入门的教程。
http://30daydo.com/article/13
 
 
运行上面的代码后,可以得到下面的曲线:
 





 
你们可以去对比一下贝斯特的收盘价,5日,10日,20日均线。是不是一样的?
就这样我们就完成了均线的获取。 是不是很简单?
 
 
  查看全部
第一节
 
安装教程在前面内容已经介绍过了,对于新手也是有点障碍,可以参照前面的文章进行一步一步操作。 http://30daydo.com/article/195
    #通过tushare获取股票信息
df=ts.get_k_data('300580',start='2017-01-12',end='2017-05-26')
#提取收盘价
closed=df['close'].values
#获取均线的数据,通过timeperiod参数来分别获取 5,10,20 日均线的数据。
ma5=talib.SMA(closed,timeperiod=5)
ma10=talib.SMA(closed,timeperiod=10)
ma20=talib.SMA(closed,timeperiod=20)

#打印出来每一个数据
print closed
print ma5
print ma10
print ma20

#通过plog函数可以很方便的绘制出每一条均线
plt.plot(closed)
plt.plot(ma5)
plt.plot(ma10)
plt.plot(ma20)
#添加网格,可有可无,只是让图像好看点
plt.grid()
#记得加这一句,不然不会显示图像
plt.show()

上面第一句使用tushare获取股票的数据,如果不知道怎么操作的,可以在这里参考,同样是入门的教程。
http://30daydo.com/article/13
 
 
运行上面的代码后,可以得到下面的曲线:
 

贝斯特曲线.PNG

 
你们可以去对比一下贝斯特的收盘价,5日,10日,20日均线。是不是一样的?
就这样我们就完成了均线的获取。 是不是很简单?
 
 
 

量化工具TA-Lib 使用例子

李魔佛 发表了文章 • 0 个评论 • 18273 次浏览 • 2017-05-26 23:51 • 来自相关话题

http://30daydo.com/article/196
 TA-Lib主要用来计算一些股市中常见的指标。
比如MACD,BOLL,均线等参数。
 #-*-coding=utf-8-*-
import Tkinter as tk
from Tkinter import *
import ttk
import matplotlib.pyplot as plt

import numpy as np
import talib as ta

series = np.random.choice([1, -1], size=200)
close = np.cumsum(series).astype(float)

# 重叠指标
def overlap_process(event):
print(event.widget.get())
overlap = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(overlap, fontproperties="SimHei")

if overlap == '布林线':
pass
elif overlap == '双指数移动平均线':
real = ta.DEMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '指数移动平均线 ':
real = ta.EMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '希尔伯特变换——瞬时趋势线':
real = ta.HT_TRENDLINE(close)
axes[1].plot(real, '')
elif overlap == '考夫曼自适应移动平均线':
real = ta.KAMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '移动平均线':
real = ta.MA(close, timeperiod=30, matype=0)
axes[1].plot(real, '')
elif overlap == 'MESA自适应移动平均':
mama, fama = ta.MAMA(close, fastlimit=0, slowlimit=0)
axes[1].plot(mama, '')
axes[1].plot(fama, '')
elif overlap == '变周期移动平均线':
real = ta.MAVP(close, periods, minperiod=2, maxperiod=30, matype=0)
axes[1].plot(real, '')
elif overlap == '简单移动平均线':
real = ta.SMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '三指数移动平均线(T3)':
real = ta.T3(close, timeperiod=5, vfactor=0)
axes[1].plot(real, '')
elif overlap == '三指数移动平均线':
real = ta.TEMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '三角形加权法 ':
real = ta.TRIMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '加权移动平均数':
real = ta.WMA(close, timeperiod=30)
axes[1].plot(real, '')
plt.show()

# 动量指标
def momentum_process(event):
print(event.widget.get())
momentum = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(momentum, fontproperties="SimHei")

if momentum == '绝对价格振荡器':
real = ta.APO(close, fastperiod=12, slowperiod=26, matype=0)
axes[1].plot(real, '')
elif momentum == '钱德动量摆动指标':
real = ta.CMO(close, timeperiod=14)
axes[1].plot(real, '')
elif momentum == '移动平均收敛/散度':
macd, macdsignal, macdhist = ta.MACD(close, fastperiod=12, slowperiod=26, signalperiod=9)
axes[1].plot(macd, '')
axes[1].plot(macdsignal, '')
axes[1].plot(macdhist, '')
elif momentum == '带可控MA类型的MACD':
macd, macdsignal, macdhist = ta.MACDEXT(close, fastperiod=12, fastmatype=0, slowperiod=26, slowmatype=0, signalperiod=9, signalmatype=0)
axes[1].plot(macd, '')
axes[1].plot(macdsignal, '')
axes[1].plot(macdhist, '')
elif momentum == '移动平均收敛/散度 固定 12/26':
macd, macdsignal, macdhist = ta.MACDFIX(close, signalperiod=9)
axes[1].plot(macd, '')
axes[1].plot(macdsignal, '')
axes[1].plot(macdhist, '')
elif momentum == '动量':
real = ta.MOM(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '比例价格振荡器':
real = ta.PPO(close, fastperiod=12, slowperiod=26, matype=0)
axes[1].plot(real, '')
elif momentum == '变化率':
real = ta.ROC(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '变化率百分比':
real = ta.ROCP(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '变化率的比率':
real = ta.ROCR(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '变化率的比率100倍':
real = ta.ROCR100(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '相对强弱指数':
real = ta.RSI(close, timeperiod=14)
axes[1].plot(real, '')
elif momentum == '随机相对强弱指标':
fastk, fastd = ta.STOCHRSI(close, timeperiod=14, fastk_period=5, fastd_period=3, fastd_matype=0)
axes[1].plot(fastk, '')
axes[1].plot(fastd, '')
elif momentum == '三重光滑EMA的日变化率':
real = ta.TRIX(close, timeperiod=30)
axes[1].plot(real, '')

plt.show()

# 周期指标
def cycle_process(event):
print(event.widget.get())
cycle = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(cycle, fontproperties="SimHei")

if cycle == '希尔伯特变换——主要的循环周期':
real = ta.HT_DCPERIOD(close)
axes[1].plot(real, '')
elif cycle == '希尔伯特变换,占主导地位的周期阶段':
real = ta.HT_DCPHASE(close)
axes[1].plot(real, '')
elif cycle == '希尔伯特变换——相量组件':
inphase, quadrature = ta.HT_PHASOR(close)
axes[1].plot(inphase, '')
axes[1].plot(quadrature, '')
elif cycle == '希尔伯特变换——正弦曲线':
sine, leadsine = ta.HT_SINE(close)
axes[1].plot(sine, '')
axes[1].plot(leadsine, '')
elif cycle == '希尔伯特变换——趋势和周期模式':
integer = ta.HT_TRENDMODE(close)
axes[1].plot(integer, '')

plt.show()


# 统计功能
def statistic_process(event):
print(event.widget.get())
statistic = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(statistic, fontproperties="SimHei")

if statistic == '线性回归':
real = ta.LINEARREG(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '线性回归角度':
real = ta.LINEARREG_ANGLE(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '线性回归截距':
real = ta.LINEARREG_INTERCEPT(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '线性回归斜率':
real = ta.LINEARREG_SLOPE(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '标准差':
real = ta.STDDEV(close, timeperiod=5, nbdev=1)
axes[1].plot(real, '')
elif statistic == '时间序列预测':
real = ta.TSF(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '方差':
real = ta.VAR(close, timeperiod=5, nbdev=1)
axes[1].plot(real, '')

plt.show()


# 数学变换
def math_transform_process(event):
print(event.widget.get())
math_transform = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(math_transform, fontproperties="SimHei")


if math_transform == '反余弦':
real = ta.ACOS(close)
axes[1].plot(real, '')
elif math_transform == '反正弦':
real = ta.ASIN(close)
axes[1].plot(real, '')
elif math_transform == '反正切':
real = ta.ATAN(close)
axes[1].plot(real, '')
elif math_transform == '向上取整':
real = ta.CEIL(close)
axes[1].plot(real, '')
elif math_transform == '余弦':
real = ta.COS(close)
axes[1].plot(real, '')
elif math_transform == '双曲余弦':
real = ta.COSH(close)
axes[1].plot(real, '')
elif math_transform == '指数':
real = ta.EXP(close)
axes[1].plot(real, '')
elif math_transform == '向下取整':
real = ta.FLOOR(close)
axes[1].plot(real, '')
elif math_transform == '自然对数':
real = ta.LN(close)
axes[1].plot(real, '')
elif math_transform == '常用对数':
real = ta.LOG10(close)
axes[1].plot(real, '')
elif math_transform == '正弦':
real = ta.SIN(close)
axes[1].plot(real, '')
elif math_transform == '双曲正弦':
real = ta.SINH(close)
axes[1].plot(real, '')
elif math_transform == '平方根':
real = ta.SQRT(close)
axes[1].plot(real, '')
elif math_transform == '正切':
real = ta.TAN(close)
axes[1].plot(real, '')
elif math_transform == '双曲正切':
real = ta.TANH(close)
axes[1].plot(real, '')

plt.show()


# 数学操作
def math_operator_process(event):
print(event.widget.get())
math_operator = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(math_operator, fontproperties="SimHei")


if math_operator == '指定的期间的最大值':
real = ta.MAX(close, timeperiod=30)
axes[1].plot(real, '')
elif math_operator == '指定的期间的最大值的索引':
integer = ta.MAXINDEX(close, timeperiod=30)
axes[1].plot(integer, '')
elif math_operator == '指定的期间的最小值':
real = ta.MIN(close, timeperiod=30)
axes[1].plot(real, '')
elif math_operator == '指定的期间的最小值的索引':
integer = ta.MININDEX(close, timeperiod=30)
axes[1].plot(integer, '')
elif math_operator == '指定的期间的最小和最大值':
min, max = ta.MINMAX(close, timeperiod=30)
axes[1].plot(min, '')
axes[1].plot(max, '')
elif math_operator == '指定的期间的最小和最大值的索引':
minidx, maxidx = ta.MINMAXINDEX(close, timeperiod=30)
axes[1].plot(minidx, '')
axes[1].plot(maxidx, '')
elif math_operator == '合计':
real = ta.SUM(close, timeperiod=30)
axes[1].plot(real, '')

plt.show()


root = tk.Tk()

# 第一行:重叠指标
rowframe1 = tk.Frame(root)
rowframe1.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe1, text="重叠指标").pack(side=tk.LEFT)

overlap_indicator = tk.StringVar() # 重叠指标
combobox1 = ttk.Combobox(rowframe1, textvariable=overlap_indicator)
combobox1['values'] = ['布林线','双指数移动平均线','指数移动平均线 ','希尔伯特变换——瞬时趋势线',
'考夫曼自适应移动平均线','移动平均线','MESA自适应移动平均','变周期移动平均线',
'简单移动平均线','三指数移动平均线(T3)','三指数移动平均线','三角形加权法 ','加权移动平均数']
combobox1.current(0)
combobox1.pack(side=tk.LEFT)

combobox1.bind('<<ComboboxSelected>>', overlap_process)


# 第二行:动量指标
rowframe2 = tk.Frame(root)
rowframe2.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe2, text="动量指标").pack(side=tk.LEFT)

momentum_indicator = tk.StringVar() # 动量指标
combobox2 = ttk.Combobox(rowframe2, textvariable=momentum_indicator)
combobox2['values'] = ['绝对价格振荡器','钱德动量摆动指标','移动平均收敛/散度','带可控MA类型的MACD',
'移动平均收敛/散度 固定 12/26','动量','比例价格振荡器','变化率','变化率百分比',
'变化率的比率','变化率的比率100倍','相对强弱指数','随机相对强弱指标','三重光滑EMA的日变化率']

combobox2.current(0)
combobox2.pack(side=tk.LEFT)

combobox2.bind('<<ComboboxSelected>>', momentum_process)



# 第三行:周期指标
rowframe3 = tk.Frame(root)
rowframe3.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe3, text="周期指标").pack(side=tk.LEFT)

cycle_indicator = tk.StringVar() # 周期指标
combobox3 = ttk.Combobox(rowframe3, textvariable=cycle_indicator)
combobox3['values'] = ['希尔伯特变换——主要的循环周期','希尔伯特变换——主要的周期阶段','希尔伯特变换——相量组件',
'希尔伯特变换——正弦曲线','希尔伯特变换——趋势和周期模式']

combobox3.current(0)
combobox3.pack(side=tk.LEFT)

combobox3.bind('<<ComboboxSelected>>', cycle_process)


# 第四行:统计功能
rowframe4 = tk.Frame(root)
rowframe4.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe4, text="统计功能").pack(side=tk.LEFT)

statistic_indicator = tk.StringVar() # 统计功能
combobox4 = ttk.Combobox(rowframe4, textvariable=statistic_indicator)
combobox4['values'] = ['贝塔系数;投资风险与股市风险系数','皮尔逊相关系数','线性回归','线性回归角度',
'线性回归截距','线性回归斜率','标准差','时间序列预测','方差']

combobox4.current(0)
combobox4.pack(side=tk.LEFT)

combobox4.bind('<<ComboboxSelected>>', statistic_process)


# 第五行:数学变换
rowframe5 = tk.Frame(root)
rowframe5.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe5, text="数学变换").pack(side=tk.LEFT)

math_transform = tk.StringVar() # 数学变换
combobox5 = ttk.Combobox(rowframe5, textvariable=math_transform_process)
combobox5['values'] = ['反余弦','反正弦','反正切','向上取整','余弦','双曲余弦','指数','向下取整',
'自然对数','常用对数','正弦','双曲正弦','平方根','正切','双曲正切']

combobox5.current(0)
combobox5.pack(side=tk.LEFT)

combobox5.bind('<<ComboboxSelected>>', math_transform_process)


# 第六行:数学操作
rowframe6 = tk.Frame(root)
rowframe6.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe6, text="数学操作").pack(side=tk.LEFT)

math_operator = tk.StringVar() # 数学操作
combobox6 = ttk.Combobox(rowframe6, textvariable=math_operator_process)
combobox6['values'] = ['指定期间的最大值','指定期间的最大值的索引','指定期间的最小值','指定期间的最小值的索引',
'指定期间的最小和最大值','指定期间的最小和最大值的索引','合计']

combobox6.current(0)
combobox6.pack(side=tk.LEFT)

combobox6.bind('<<ComboboxSelected>>', math_operator_process)




root.mainloop() 查看全部
http://30daydo.com/article/196
 TA-Lib主要用来计算一些股市中常见的指标。
比如MACD,BOLL,均线等参数。
 
#-*-coding=utf-8-*-
import Tkinter as tk
from Tkinter import *
import ttk
import matplotlib.pyplot as plt

import numpy as np
import talib as ta

series = np.random.choice([1, -1], size=200)
close = np.cumsum(series).astype(float)

# 重叠指标
def overlap_process(event):
print(event.widget.get())
overlap = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(overlap, fontproperties="SimHei")

if overlap == '布林线':
pass
elif overlap == '双指数移动平均线':
real = ta.DEMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '指数移动平均线 ':
real = ta.EMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '希尔伯特变换——瞬时趋势线':
real = ta.HT_TRENDLINE(close)
axes[1].plot(real, '')
elif overlap == '考夫曼自适应移动平均线':
real = ta.KAMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '移动平均线':
real = ta.MA(close, timeperiod=30, matype=0)
axes[1].plot(real, '')
elif overlap == 'MESA自适应移动平均':
mama, fama = ta.MAMA(close, fastlimit=0, slowlimit=0)
axes[1].plot(mama, '')
axes[1].plot(fama, '')
elif overlap == '变周期移动平均线':
real = ta.MAVP(close, periods, minperiod=2, maxperiod=30, matype=0)
axes[1].plot(real, '')
elif overlap == '简单移动平均线':
real = ta.SMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '三指数移动平均线(T3)':
real = ta.T3(close, timeperiod=5, vfactor=0)
axes[1].plot(real, '')
elif overlap == '三指数移动平均线':
real = ta.TEMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '三角形加权法 ':
real = ta.TRIMA(close, timeperiod=30)
axes[1].plot(real, '')
elif overlap == '加权移动平均数':
real = ta.WMA(close, timeperiod=30)
axes[1].plot(real, '')
plt.show()

# 动量指标
def momentum_process(event):
print(event.widget.get())
momentum = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(momentum, fontproperties="SimHei")

if momentum == '绝对价格振荡器':
real = ta.APO(close, fastperiod=12, slowperiod=26, matype=0)
axes[1].plot(real, '')
elif momentum == '钱德动量摆动指标':
real = ta.CMO(close, timeperiod=14)
axes[1].plot(real, '')
elif momentum == '移动平均收敛/散度':
macd, macdsignal, macdhist = ta.MACD(close, fastperiod=12, slowperiod=26, signalperiod=9)
axes[1].plot(macd, '')
axes[1].plot(macdsignal, '')
axes[1].plot(macdhist, '')
elif momentum == '带可控MA类型的MACD':
macd, macdsignal, macdhist = ta.MACDEXT(close, fastperiod=12, fastmatype=0, slowperiod=26, slowmatype=0, signalperiod=9, signalmatype=0)
axes[1].plot(macd, '')
axes[1].plot(macdsignal, '')
axes[1].plot(macdhist, '')
elif momentum == '移动平均收敛/散度 固定 12/26':
macd, macdsignal, macdhist = ta.MACDFIX(close, signalperiod=9)
axes[1].plot(macd, '')
axes[1].plot(macdsignal, '')
axes[1].plot(macdhist, '')
elif momentum == '动量':
real = ta.MOM(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '比例价格振荡器':
real = ta.PPO(close, fastperiod=12, slowperiod=26, matype=0)
axes[1].plot(real, '')
elif momentum == '变化率':
real = ta.ROC(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '变化率百分比':
real = ta.ROCP(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '变化率的比率':
real = ta.ROCR(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '变化率的比率100倍':
real = ta.ROCR100(close, timeperiod=10)
axes[1].plot(real, '')
elif momentum == '相对强弱指数':
real = ta.RSI(close, timeperiod=14)
axes[1].plot(real, '')
elif momentum == '随机相对强弱指标':
fastk, fastd = ta.STOCHRSI(close, timeperiod=14, fastk_period=5, fastd_period=3, fastd_matype=0)
axes[1].plot(fastk, '')
axes[1].plot(fastd, '')
elif momentum == '三重光滑EMA的日变化率':
real = ta.TRIX(close, timeperiod=30)
axes[1].plot(real, '')

plt.show()

# 周期指标
def cycle_process(event):
print(event.widget.get())
cycle = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(cycle, fontproperties="SimHei")

if cycle == '希尔伯特变换——主要的循环周期':
real = ta.HT_DCPERIOD(close)
axes[1].plot(real, '')
elif cycle == '希尔伯特变换,占主导地位的周期阶段':
real = ta.HT_DCPHASE(close)
axes[1].plot(real, '')
elif cycle == '希尔伯特变换——相量组件':
inphase, quadrature = ta.HT_PHASOR(close)
axes[1].plot(inphase, '')
axes[1].plot(quadrature, '')
elif cycle == '希尔伯特变换——正弦曲线':
sine, leadsine = ta.HT_SINE(close)
axes[1].plot(sine, '')
axes[1].plot(leadsine, '')
elif cycle == '希尔伯特变换——趋势和周期模式':
integer = ta.HT_TRENDMODE(close)
axes[1].plot(integer, '')

plt.show()


# 统计功能
def statistic_process(event):
print(event.widget.get())
statistic = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(statistic, fontproperties="SimHei")

if statistic == '线性回归':
real = ta.LINEARREG(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '线性回归角度':
real = ta.LINEARREG_ANGLE(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '线性回归截距':
real = ta.LINEARREG_INTERCEPT(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '线性回归斜率':
real = ta.LINEARREG_SLOPE(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '标准差':
real = ta.STDDEV(close, timeperiod=5, nbdev=1)
axes[1].plot(real, '')
elif statistic == '时间序列预测':
real = ta.TSF(close, timeperiod=14)
axes[1].plot(real, '')
elif statistic == '方差':
real = ta.VAR(close, timeperiod=5, nbdev=1)
axes[1].plot(real, '')

plt.show()


# 数学变换
def math_transform_process(event):
print(event.widget.get())
math_transform = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(math_transform, fontproperties="SimHei")


if math_transform == '反余弦':
real = ta.ACOS(close)
axes[1].plot(real, '')
elif math_transform == '反正弦':
real = ta.ASIN(close)
axes[1].plot(real, '')
elif math_transform == '反正切':
real = ta.ATAN(close)
axes[1].plot(real, '')
elif math_transform == '向上取整':
real = ta.CEIL(close)
axes[1].plot(real, '')
elif math_transform == '余弦':
real = ta.COS(close)
axes[1].plot(real, '')
elif math_transform == '双曲余弦':
real = ta.COSH(close)
axes[1].plot(real, '')
elif math_transform == '指数':
real = ta.EXP(close)
axes[1].plot(real, '')
elif math_transform == '向下取整':
real = ta.FLOOR(close)
axes[1].plot(real, '')
elif math_transform == '自然对数':
real = ta.LN(close)
axes[1].plot(real, '')
elif math_transform == '常用对数':
real = ta.LOG10(close)
axes[1].plot(real, '')
elif math_transform == '正弦':
real = ta.SIN(close)
axes[1].plot(real, '')
elif math_transform == '双曲正弦':
real = ta.SINH(close)
axes[1].plot(real, '')
elif math_transform == '平方根':
real = ta.SQRT(close)
axes[1].plot(real, '')
elif math_transform == '正切':
real = ta.TAN(close)
axes[1].plot(real, '')
elif math_transform == '双曲正切':
real = ta.TANH(close)
axes[1].plot(real, '')

plt.show()


# 数学操作
def math_operator_process(event):
print(event.widget.get())
math_operator = event.widget.get()

upperband, middleband, lowerband = ta.BBANDS(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
fig, axes = plt.subplots(2, 1, sharex=True)
ax1, ax2 = axes[0], axes[1]
axes[0].plot(close, '', markersize=3)
axes[0].plot(upperband, '')
axes[0].plot(middleband, '')
axes[0].plot(lowerband, '')
axes[0].set_title(math_operator, fontproperties="SimHei")


if math_operator == '指定的期间的最大值':
real = ta.MAX(close, timeperiod=30)
axes[1].plot(real, '')
elif math_operator == '指定的期间的最大值的索引':
integer = ta.MAXINDEX(close, timeperiod=30)
axes[1].plot(integer, '')
elif math_operator == '指定的期间的最小值':
real = ta.MIN(close, timeperiod=30)
axes[1].plot(real, '')
elif math_operator == '指定的期间的最小值的索引':
integer = ta.MININDEX(close, timeperiod=30)
axes[1].plot(integer, '')
elif math_operator == '指定的期间的最小和最大值':
min, max = ta.MINMAX(close, timeperiod=30)
axes[1].plot(min, '')
axes[1].plot(max, '')
elif math_operator == '指定的期间的最小和最大值的索引':
minidx, maxidx = ta.MINMAXINDEX(close, timeperiod=30)
axes[1].plot(minidx, '')
axes[1].plot(maxidx, '')
elif math_operator == '合计':
real = ta.SUM(close, timeperiod=30)
axes[1].plot(real, '')

plt.show()


root = tk.Tk()

# 第一行:重叠指标
rowframe1 = tk.Frame(root)
rowframe1.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe1, text="重叠指标").pack(side=tk.LEFT)

overlap_indicator = tk.StringVar() # 重叠指标
combobox1 = ttk.Combobox(rowframe1, textvariable=overlap_indicator)
combobox1['values'] = ['布林线','双指数移动平均线','指数移动平均线 ','希尔伯特变换——瞬时趋势线',
'考夫曼自适应移动平均线','移动平均线','MESA自适应移动平均','变周期移动平均线',
'简单移动平均线','三指数移动平均线(T3)','三指数移动平均线','三角形加权法 ','加权移动平均数']
combobox1.current(0)
combobox1.pack(side=tk.LEFT)

combobox1.bind('<<ComboboxSelected>>', overlap_process)


# 第二行:动量指标
rowframe2 = tk.Frame(root)
rowframe2.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe2, text="动量指标").pack(side=tk.LEFT)

momentum_indicator = tk.StringVar() # 动量指标
combobox2 = ttk.Combobox(rowframe2, textvariable=momentum_indicator)
combobox2['values'] = ['绝对价格振荡器','钱德动量摆动指标','移动平均收敛/散度','带可控MA类型的MACD',
'移动平均收敛/散度 固定 12/26','动量','比例价格振荡器','变化率','变化率百分比',
'变化率的比率','变化率的比率100倍','相对强弱指数','随机相对强弱指标','三重光滑EMA的日变化率']

combobox2.current(0)
combobox2.pack(side=tk.LEFT)

combobox2.bind('<<ComboboxSelected>>', momentum_process)



# 第三行:周期指标
rowframe3 = tk.Frame(root)
rowframe3.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe3, text="周期指标").pack(side=tk.LEFT)

cycle_indicator = tk.StringVar() # 周期指标
combobox3 = ttk.Combobox(rowframe3, textvariable=cycle_indicator)
combobox3['values'] = ['希尔伯特变换——主要的循环周期','希尔伯特变换——主要的周期阶段','希尔伯特变换——相量组件',
'希尔伯特变换——正弦曲线','希尔伯特变换——趋势和周期模式']

combobox3.current(0)
combobox3.pack(side=tk.LEFT)

combobox3.bind('<<ComboboxSelected>>', cycle_process)


# 第四行:统计功能
rowframe4 = tk.Frame(root)
rowframe4.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe4, text="统计功能").pack(side=tk.LEFT)

statistic_indicator = tk.StringVar() # 统计功能
combobox4 = ttk.Combobox(rowframe4, textvariable=statistic_indicator)
combobox4['values'] = ['贝塔系数;投资风险与股市风险系数','皮尔逊相关系数','线性回归','线性回归角度',
'线性回归截距','线性回归斜率','标准差','时间序列预测','方差']

combobox4.current(0)
combobox4.pack(side=tk.LEFT)

combobox4.bind('<<ComboboxSelected>>', statistic_process)


# 第五行:数学变换
rowframe5 = tk.Frame(root)
rowframe5.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe5, text="数学变换").pack(side=tk.LEFT)

math_transform = tk.StringVar() # 数学变换
combobox5 = ttk.Combobox(rowframe5, textvariable=math_transform_process)
combobox5['values'] = ['反余弦','反正弦','反正切','向上取整','余弦','双曲余弦','指数','向下取整',
'自然对数','常用对数','正弦','双曲正弦','平方根','正切','双曲正切']

combobox5.current(0)
combobox5.pack(side=tk.LEFT)

combobox5.bind('<<ComboboxSelected>>', math_transform_process)


# 第六行:数学操作
rowframe6 = tk.Frame(root)
rowframe6.pack(side=tk.TOP, ipadx=3, ipady=3)
tk.Label(rowframe6, text="数学操作").pack(side=tk.LEFT)

math_operator = tk.StringVar() # 数学操作
combobox6 = ttk.Combobox(rowframe6, textvariable=math_operator_process)
combobox6['values'] = ['指定期间的最大值','指定期间的最大值的索引','指定期间的最小值','指定期间的最小值的索引',
'指定期间的最小和最大值','指定期间的最小和最大值的索引','合计']

combobox6.current(0)
combobox6.pack(side=tk.LEFT)

combobox6.bind('<<ComboboxSelected>>', math_operator_process)




root.mainloop()

quantdigger 安装教程 & 安装出现的问题解决

李魔佛 发表了文章 • 4 个评论 • 6571 次浏览 • 2017-05-25 22:00 • 来自相关话题

http://30daydo.com/publish/article/195
 
 win7
可以下载https://github.com/Rockyzsu/quantdigger 然后解压, 运行以下python命令: 
python setupscripts/install.py 或者 pip install quantdigger
 
如果出现一些库文件的依赖关系导致出错
fatal error C1083: Cannot open include file: 'ta_libc.
 
那么说明你的TA-Lib的这个库没有安装好。
 
先尝试 pip install TA-Lib 看能否安装成功。如果失败了,继续下面的: 
下载http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-msvc.zip 然后解压放在c盘根目录下 (如: C:\ta-lib)。
 
再运行pip install TA-Lib
 
然后重新运行 python setupscripts/install.py 查看全部
http://30daydo.com/publish/article/195
 
 win7
可以下载https://github.com/Rockyzsu/quantdigger 然后解压, 运行以下python命令: 
python setupscripts/install.py 或者 pip install quantdigger
 
如果出现一些库文件的依赖关系导致出错
fatal error C1083: Cannot open include file: 'ta_libc.
 
那么说明你的TA-Lib的这个库没有安装好。
 
先尝试 pip install TA-Lib 看能否安装成功。如果失败了,继续下面的: 
下载http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-msvc.zip 然后解压放在c盘根目录下 (如: C:\ta-lib)。
 
再运行pip install TA-Lib
 
然后重新运行 python setupscripts/install.py

量化交易 获取获取上市公司年报

李魔佛 发表了文章 • 0 个评论 • 5772 次浏览 • 2017-05-22 11:37 • 来自相关话题

http://30daydo.com/article/192
 
 tushare有一个函数, ts.get_report_data(年份,季度), 可以获取每一年的季度的业绩。

如果想要获取上市公司的年报,只要吧季度参数改为4即可 

例如 要获取 中国银行的2016年的年报

df=ts.get_report_data(2016,4)

print df[df['code']=='601988']


输出的结果如下:
 
In [4]: print df[df['code']=='601988']
        code  name   eps  eps_yoy  bvps    roe  epcf  net_profits  \
1826  601988  中国银行  0.54    -3.57  4.46  12.58   NaN   16457800.0

      profits_yoy  distrib report_date
1826        -3.67  10派1.68       04-01
 
 
  查看全部
http://30daydo.com/article/192
 
 tushare有一个函数, ts.get_report_data(年份,季度), 可以获取每一年的季度的业绩。

如果想要获取上市公司的年报,只要吧季度参数改为4即可 

例如 要获取 中国银行的2016年的年报

df=ts.get_report_data(2016,4)

print df[df['code']=='601988']


输出的结果如下:
 
In [4]: print df[df['code']=='601988']
        code  name   eps  eps_yoy  bvps    roe  epcf  net_profits  \
1826  601988  中国银行  0.54    -3.57  4.46  12.58   NaN   16457800.0

      profits_yoy  distrib report_date
1826        -3.67  10派1.68       04-01
 
 
 

python 多线程监测股票涨停板打开 并通知用户

李魔佛 发表了文章 • 2 个评论 • 12664 次浏览 • 2017-05-17 12:27 • 来自相关话题

相信打板一族一个习惯就是需要盯盘,这个一件很累的事情。 需要时刻盯着分时走势,委托单的数目,涨停打开,回封。
 
下面写了一个用python监测准备要打开涨停板的股票。 用多线程实现,可以支持同时监测多个股票,如果遇到撤单或者托单数少于某个临界值,说明涨停很快就要被打开。
 
# -*-coding=utf-8-*-
__author__ = 'Rocky'
'''
http://30daydo.com
Contact: weigesysu@qq.com
'''
import smtplib, time, os, datetime
from email.mime.text import MIMEText
from email.header import Header
from toolkit import Toolkit
from email.mime.multipart import MIMEMultipart
from email import Encoders, Utils
from toolkit import Toolkit
import tushare as ts
from pandas import Series
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import threading

#监测涨停板开板监测
class break_monitor():
def __init__(self,send=True):
self.send=send
if self.send==True:
cfg = Toolkit.getUserData('data.cfg')
from_mail = cfg['from_mail']
password = cfg['password']
to_mail = cfg['to_mail']
smtp_server = 'smtp.qq.com'

self.server = smtp_server
self.username = from_mail.split("@")[0]
self.from_mail = from_mail
self.password = password
self.to_mail = to_mail
# 初始化邮箱设置读取需要股票信息
# 这样子只登陆一次
try:
self.smtp = smtplib.SMTP_SSL(port=465)
self.smtp.connect(self.server)
self.smtp.login(self.username, self.password)
except smtplib.SMTPException, e:
print e
return 0
self.bases = pd.read_csv('bases.csv', dtype={'code': np.str})
self.stocklist = Toolkit.read_stock('monitor_list.log')



def send_txt(self, name, content):

subject = '%s' % name
self.msg = MIMEText(content, 'plain', 'utf-8')
self.msg['to'] = self.to_mail
self.msg['from'] = self.from_mail
self.msg['Subject'] = subject
self.msg['Date'] = Utils.formatdate(localtime=1)
try:
self.smtp.sendmail(self.msg['from'], self.msg['to'], self.msg.as_string())
self.smtp.quit()
print "sent"
except smtplib.SMTPException, e:
print e
return 0

#开板提示
def break_ceil(self, code):
print threading.current_thread().name
while 1:
#print code
time.sleep(2)
try:
df = ts.get_realtime_quotes(code)
except:
time.sleep(5)
continue
v = long(df['b1_v'].values[0])

if v <= 1000:
print datetime.datetime.now().strftime("%H:%M:%S")
print u"小于万手,小心!跑"
if self.send==True:
self.push_msg('break', 10, 10, 'down')
#这里可以优化,不必每次都登陆。


def monitor_break(self,send=True):
thread_num = len(self.stocklist)
thread_list = []
join_list = []
for i in range(thread_num):
t = threading.Thread(target=self.break_ceil, args=(self.stocklist[i],))
thread_list.append(t)

for j in thread_list:
j.start()

for k in thread_list:
k.join()


if __name__ == '__main__':
path = os.path.join(os.getcwd(), 'data')
if os.path.exists(path) == False:
os.mkdir(path)
os.chdir(path)
obj = break_monitor(send=False)
obj.monitor_break()

用法: 创建一个data文件夹,里面存放一个bases.csv文件,这个文件保存了A股的所有股票基本信息。 至于如何获取。请参看连接:
 
然后创建一个monitor_list.log的文件,把你要监测的股票代码写进去,一个代码写一行。
 
如果你需要程序发信息到你的手机或者邮箱,那么在data文件夹下创建一个data.cfg的文件,里面的内容格式为:
 
from_mail=从这个邮箱发出,我测试的是QQ邮箱
password=发出邮箱的密码
to_mail=需要发送到的通知邮箱,推荐139邮箱,这个会推送到短信手机,等同于发一个短信给你。
 
然后直接运行就可以了。 查看全部
相信打板一族一个习惯就是需要盯盘,这个一件很累的事情。 需要时刻盯着分时走势,委托单的数目,涨停打开,回封。
 
下面写了一个用python监测准备要打开涨停板的股票。 用多线程实现,可以支持同时监测多个股票,如果遇到撤单或者托单数少于某个临界值,说明涨停很快就要被打开。
 
# -*-coding=utf-8-*-
__author__ = 'Rocky'
'''
http://30daydo.com
Contact: weigesysu@qq.com
'''
import smtplib, time, os, datetime
from email.mime.text import MIMEText
from email.header import Header
from toolkit import Toolkit
from email.mime.multipart import MIMEMultipart
from email import Encoders, Utils
from toolkit import Toolkit
import tushare as ts
from pandas import Series
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import threading

#监测涨停板开板监测
class break_monitor():
def __init__(self,send=True):
self.send=send
if self.send==True:
cfg = Toolkit.getUserData('data.cfg')
from_mail = cfg['from_mail']
password = cfg['password']
to_mail = cfg['to_mail']
smtp_server = 'smtp.qq.com'

self.server = smtp_server
self.username = from_mail.split("@")[0]
self.from_mail = from_mail
self.password = password
self.to_mail = to_mail
# 初始化邮箱设置读取需要股票信息
# 这样子只登陆一次
try:
self.smtp = smtplib.SMTP_SSL(port=465)
self.smtp.connect(self.server)
self.smtp.login(self.username, self.password)
except smtplib.SMTPException, e:
print e
return 0
self.bases = pd.read_csv('bases.csv', dtype={'code': np.str})
self.stocklist = Toolkit.read_stock('monitor_list.log')



def send_txt(self, name, content):

subject = '%s' % name
self.msg = MIMEText(content, 'plain', 'utf-8')
self.msg['to'] = self.to_mail
self.msg['from'] = self.from_mail
self.msg['Subject'] = subject
self.msg['Date'] = Utils.formatdate(localtime=1)
try:
self.smtp.sendmail(self.msg['from'], self.msg['to'], self.msg.as_string())
self.smtp.quit()
print "sent"
except smtplib.SMTPException, e:
print e
return 0

#开板提示
def break_ceil(self, code):
print threading.current_thread().name
while 1:
#print code
time.sleep(2)
try:
df = ts.get_realtime_quotes(code)
except:
time.sleep(5)
continue
v = long(df['b1_v'].values[0])

if v <= 1000:
print datetime.datetime.now().strftime("%H:%M:%S")
print u"小于万手,小心!跑"
if self.send==True:
self.push_msg('break', 10, 10, 'down')
#这里可以优化,不必每次都登陆。


def monitor_break(self,send=True):
thread_num = len(self.stocklist)
thread_list = []
join_list = []
for i in range(thread_num):
t = threading.Thread(target=self.break_ceil, args=(self.stocklist[i],))
thread_list.append(t)

for j in thread_list:
j.start()

for k in thread_list:
k.join()


if __name__ == '__main__':
path = os.path.join(os.getcwd(), 'data')
if os.path.exists(path) == False:
os.mkdir(path)
os.chdir(path)
obj = break_monitor(send=False)
obj.monitor_break()

用法: 创建一个data文件夹,里面存放一个bases.csv文件,这个文件保存了A股的所有股票基本信息。 至于如何获取。请参看连接:
 
然后创建一个monitor_list.log的文件,把你要监测的股票代码写进去,一个代码写一行。
 
如果你需要程序发信息到你的手机或者邮箱,那么在data文件夹下创建一个data.cfg的文件,里面的内容格式为:
 
from_mail=从这个邮箱发出,我测试的是QQ邮箱
password=发出邮箱的密码
to_mail=需要发送到的通知邮箱,推荐139邮箱,这个会推送到短信手机,等同于发一个短信给你。
 
然后直接运行就可以了。

统计新股的连板天数,通过累计换手率预测开板时机

李魔佛 发表了文章 • 0 个评论 • 5175 次浏览 • 2017-05-11 17:12 • 来自相关话题

http://30daydo.com/article/182
 
对于一只新股,不少人会盯着它什么时候开板。 不过对于一般散户,如果换手率低于5%的一字涨停,也很难挤进去。 
那么今天我们来试一下计算新股的开板前的连板天数。# -*-coding=utf-8-*-
__author__ = 'Rocky'
'''
http://30daydo.com
Contact: weigesysu@qq.com
'''
#分析新股的开板时机
import tushare as ts
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
class New_Stock_Break():
def __init__(self):
#为了文件整齐,新建一个文件夹data用来专门存放数据
current = os.getcwd()
folder = os.path.join(current, 'data')
if os.path.exists(folder) == False:
os.mkdir(folder)
os.chdir(folder)
#调用tushare接口,获取A股信息
df0=ts.get_stock_basics()
#df0=pd.read_csv('bases.csv',dtype={'code':np.str})
self.bases=df0.sort_values('timeToMarket',ascending=False)

#获取样本, 获取最近一个年的新股情况

self.cxg=self.bases[(self.bases['timeToMarket']>20160101) & (self.bases['timeToMarket']<20170101)]
self.codes= self.cxg['code'].values

def calc_open_by_percent(self,code):
cont=100000000
#total_vol=self.bases[self.bases['code']==code]['totals'].values[0]
acutal_vol=self.bases[self.bases['code']==code]['outstanding'].values[0]
all_vol= acutal_vol*cont
df1=ts.get_k_data(code)
i=1
while 1:
s=df1.ix[1]
if s['high']!=s['low']:
#date=s['date']
break
i=i+1

j=i-1
date_end=df1.ix[j]['date']
date_start=df1.ix[0]['date']
df3=df1[(df1['date']>=date_start) & (df1['date']<=date_end)]
v_total_break=df3['volume'].sum()
l=len(df3)
print l
print v_total_break
rate=v_total_break*100*100.00/all_vol #手和股 注意
print round(rate,6)
return rate,l


def getData(self):
result=
max_line=
k=
for i in self.codes:
print i
name=self.bases[self.bases['code']==i]['name'].values[0]
rate,l=self.calc_open_by_percent(i)
if rate is not None:
result.append(rate)
max_line.append([name,l,rate])
k.append(l)
#写入文件
f=open('2016-2017-cixin.csv','w')
for x in max_line:
#f.write(';'.join(x))
f.write(x[0])
f.write('-')
f.write(str(x[1]))
f.write('-')
f.write(str(x[2]))
f.write('\n')

f.close()

def main():
obj=New_Stock_Break()
obj.testcase2()

main() 
运行后得到的数据如下:





 
你可以修改部分参数,可以获取每一年,或者每一个月的新股情况。
 
从上面的数据可以获取得到,最多的连班是海天精工的29板, 海天精工-29-12.8248076923 
累计的换手率达到了12.8。
 
当然上面的是在2016年IPO速度还没那么快的时候,2017年平均不到10个板就开了。 
 
附上抓取的数据文件
 
 链接: https://pan.baidu.com/s/1c1LpOZ2 密码: r3yk 查看全部
http://30daydo.com/article/182
 
对于一只新股,不少人会盯着它什么时候开板。 不过对于一般散户,如果换手率低于5%的一字涨停,也很难挤进去。 
那么今天我们来试一下计算新股的开板前的连板天数。
# -*-coding=utf-8-*-
__author__ = 'Rocky'
'''
http://30daydo.com
Contact: weigesysu@qq.com
'''
#分析新股的开板时机
import tushare as ts
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
class New_Stock_Break():
def __init__(self):
#为了文件整齐,新建一个文件夹data用来专门存放数据
current = os.getcwd()
folder = os.path.join(current, 'data')
if os.path.exists(folder) == False:
os.mkdir(folder)
os.chdir(folder)
#调用tushare接口,获取A股信息
df0=ts.get_stock_basics()
#df0=pd.read_csv('bases.csv',dtype={'code':np.str})
self.bases=df0.sort_values('timeToMarket',ascending=False)

#获取样本, 获取最近一个年的新股情况

self.cxg=self.bases[(self.bases['timeToMarket']>20160101) & (self.bases['timeToMarket']<20170101)]
self.codes= self.cxg['code'].values

def calc_open_by_percent(self,code):
cont=100000000
#total_vol=self.bases[self.bases['code']==code]['totals'].values[0]
acutal_vol=self.bases[self.bases['code']==code]['outstanding'].values[0]
all_vol= acutal_vol*cont
df1=ts.get_k_data(code)
i=1
while 1:
s=df1.ix[1]
if s['high']!=s['low']:
#date=s['date']
break
i=i+1

j=i-1
date_end=df1.ix[j]['date']
date_start=df1.ix[0]['date']
df3=df1[(df1['date']>=date_start) & (df1['date']<=date_end)]
v_total_break=df3['volume'].sum()
l=len(df3)
print l
print v_total_break
rate=v_total_break*100*100.00/all_vol #手和股 注意
print round(rate,6)
return rate,l


def getData(self):
result=
max_line=
k=
for i in self.codes:
print i
name=self.bases[self.bases['code']==i]['name'].values[0]
rate,l=self.calc_open_by_percent(i)
if rate is not None:
result.append(rate)
max_line.append([name,l,rate])
k.append(l)
#写入文件
f=open('2016-2017-cixin.csv','w')
for x in max_line:
#f.write(';'.join(x))
f.write(x[0])
f.write('-')
f.write(str(x[1]))
f.write('-')
f.write(str(x[2]))
f.write('\n')

f.close()

def main():
obj=New_Stock_Break()
obj.testcase2()

main()
 
运行后得到的数据如下:

开板.PNG

 

你可以修改部分参数,可以获取每一年,或者每一个月的新股情况。
 
从上面的数据可以获取得到,最多的连班是海天精工的29板, 海天精工-29-12.8248076923 
累计的换手率达到了12.8。
 
当然上面的是在2016年IPO速度还没那么快的时候,2017年平均不到10个板就开了。 
 
附上抓取的数据文件
 
 链接: https://pan.baidu.com/s/1c1LpOZ2 密码: r3yk

聚币网/coinegg API使用教程 附demo代码

李魔佛 发表了文章 • 56 个评论 • 22314 次浏览 • 2017-05-11 09:05 • 来自相关话题

******* 2018.14 更新 ***********
现在聚币网已经被关闭了,但是所有的币都可以转移到CoinEgg网了,币种和以前一模一样,只是用户参与度减少了很多,市场不是一个有效的市场,但是这对于操盘手来说,更加是一个收益大的地方。
使用下面链接注册后,用户可以返30%的佣金。 其实也无所谓,佣金不会很多,一次也就几分钱到几毛钱,自己去官网注册也可以。看个人心情啦。
 
http://www.coinegg.com/user/register?inv=7d91a
 
 后续会就coinegg写一个自动交易的系统出来
 

******* 8.28 更新 ***********
不少人反应签名不通过,经过调试,发现是加密前的字符拼接的顺序问题,这个拼接顺序要和你post上去的顺序要一致,才能通过。如果出现104的返回代码,说明是你的顺序问题,说明你的签名没有成功。
 
贴代码说明下: 使用字典循环,就可以知道正确的拼接顺序。 下面的代码是获取成交订单的。 def Trade_list(self, coin):
'''
Trade_list(挂单查询)
您指定时间后的挂单,可以根据类型查询,比如查看正在挂单和全部挂单
Path:/api/v1/trade_list/
Request类型:POST
参数
key - API key
signature - signature
nonce - nonce
since - unix timestamp(utc timezone) default == 0, i.e. 返回所有
coin - 币种简称,例如btc、ltc、xas
type - 挂单类型[open:正在挂单, all:所有挂单]

返回JSON dictionary
id - 挂单ID
datetime - date and time
type - "buy" or "sell"
price - price
amount_original - 下单时数量
amount_outstanding - 当前剩余数量
'''
url = self.host + '/api/v1/trade_list/'
time.sleep(random.random())
nonce = self.get_nonce_time()
types = 'all'
since = 0
parameters = {'key': self.public_key, 'nonce': str(nonce), 'type': types, 'coin': coin, 'signature': ''}
# print parameters
post_data = ''
for k, v in parameters.items():
if not isinstance(v, str):
#if type(v) is not types.StringType:
v = str(v)
post_data = post_data + k
post_data = post_data + '=' + v + '&'

#print 'post-data:\n',post_data
post_data = post_data[:-1]
post_data = post_data.replace('&signature=', '')
#print post_data

signature = hmac.new(self.md5, post_data, digestmod=hashlib.sha256).digest()
sig = self.toHex(signature)
parameters['signature'] = sig
#print parameters
r = requests.post(url=url, data=parameters)
s = r.json()
#print s
return s
 
如果还是没有解决的话就网站内私信我看看问题所在。

******************************************* 原文内容 ***************************************************
 

 官方有API的文档,可是这个文档就像一个草稿一样,两个基本例子都没有。 所以自己摸索一下,自己写一个现成的例子给大家,可以有个参考。 下面的例子亲测成功。 
 
首先看一下官方的API文档:

一、API使用说明

1、请求过程说明

1.1 构造请求数据,用户数据按照Jubi提供的接口规则,通过程序生成签名和要传输给Jubi的数据集合;

1.2 发送请求数据,把构造完成的数据集合通过POST/GET提交的方式传递给Jubi;

1.3 Jubi对请求数据进行处理,服务器在接收到请求后,会首先进行安全校验,验证通过后便会处理该次发送过来的请求;

1.4 返回响应结果数据,Jubi把响应结果以JSON的格式反馈给用户,具体的响应格式,错误代码参见接口部分;

1.5 对获取的返回结果数据进行处理;

2、安全认证

所有的private API都需要经过认证

Api的申请可以到财务中心 -> API,申请得到私钥和公钥,私钥Jubi将不做储存,一旦丢失将无法找回

注意:请勿向任何人泄露这两个参数,这像您的密码一样重要

2.签名机制

每次请求private api 都需要验证签名,发送的参数示例:

$param = array(

amount => 1,

price => 10000,

type => 'buy',

nonce => 141377098123

key => 5zi7w-4mnes-swmc4-egg9b-f2iqw-396z4-g541b

signature => 459c69d25c496765191582d9611028b9974830e9dfafd762854669809290ed82

);

nonce 可以理解为一个递增的整数:http://zh.wikipedia.org/wiki/Nonce

key 是申请到的公钥

signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

 

 
 
  
首先聚币的行情是使用网络爬虫获取的,而说明中给出了一系列的参数,你需要做的就是把这些参数填充上去。
 
如果你只是想要获取行情,那么事情容易很多。 def real_time_ticker(coin):
url = 'https://www.jubi.com/api/v1/ticker/'
try:
data = requests.post(url, data={'coin': coin}).json()

except Exception ,e:
print e
return data
上面代码展示的时候获取实时的行情。委一和买一的价格,数量,和当前成交的数量,价格。
 按照上面的格式,把参数coin填上去,比如要获取泽塔币, real_time_ticker('zet') 就会返回获取的数据。{u'sell': u'0.179000', u'volume': 21828245.102822, u'buy': u'0.175010', u'last': u'0.179000', u'vol': 108290769.9171, u'high': u'0.289000', u'low': u'0.119141'}
 
 
所有的private API都需要经过认证, 就是说如果你要进行交易,委托,下单,你就需要使用私钥和公钥,并进行一系列的加密。

每次请求private api 都需要验证签名,发送的参数示例:

$param = array(

amount => 1,

price => 10000,

type => 'buy',

nonce => 141377098123

key => 5zi7w-4mnes-swmc4-egg9b-f2iqw-396z4-g541b

signature => 459c69d25c496765191582d9611028b9974830e9dfafd762854669809290ed82

);

nonce 可以理解为一个递增的整数:http://zh.wikipedia.org/wiki/Nonce

key 是申请到的公钥

signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

 
 
比如下单:

Trade_add(下单)
Path:/api/v1/trade_add/
Request类型:POST
 
参数
key - API key
signature - signature
nonce - nonce
amount - 购买数量
price - 购买价格
type - 买单或者卖单
coin - 币种简称,例如btc、ltc、xas
id - 挂单ID
result - true(成功), false(失败)
{"result":true, "id":"11"}
 
返回JSON dictionary
id - 挂单ID
result - true(成功), false(失败)
 
返回结果示例:
{"result":true, "id":"11"}
 


首先解决nonce。
 
在维基百科中
在安全工程中,Nonce是一个在加密通信只能使用一次的数字。在认证协议中,它往往是一个随机或伪随机数,以避免重放攻击。Nonce也用于流密码以确保安全。如果需要使用相同的密钥加密一个以上的消息,就需要Nonce来确保不同的消息与该密钥加密的密钥流不同。
 
结合stackoverflow, nonce只是一个12位的随机数。
可以用以下方法获得这个随机数 def get_nonce(self):
lens=12
return ''.join([str(random.randint(0, 9)) for i in range(lens)])
 聚币中的nonce的位数是12位,所以lens定义为12
 
或者可以直接用时间函数生成: def get_nonce_time(self):
lens = 12
curr_stamp = time.time()*100
nonece=int(curr_stamp)
return nonece
 
然后是signature。
signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

先把私钥进行md5处理 def getHash(self,s):
m=hashlib.md5()
m.update(s)
return m.hexdigest()
只要把私钥传入函数getHash就可以得到一个md5处理过的字符串。
 
私钥是聚币网给每个用户分配的字符串,是唯一的,这里假设为private_key=123456789吧,具体是多少,在你的聚币网设置里面可以找到。
sha_256key=self.getHash(private_key)
 
按照要求吧 你要post的数据字符串连起来nonce=self.get_nonce_time
type='buy'
amount='10000'
key='xxxxxxxxxxx‘ #这个是聚币网给你的公钥,同样在设置里头可以找到
price='10' #你要设置的价格为10
coin='zet'
message = "amount=“+amount+”&nonce="+str(nonce)+"&type="+type+"&key="+key+'&price="+price+"&coin"+coin

signature = hmac.new(sha_256key, message, digestmod=hashlib.sha256).digest()

这样获得signature之后,就可以通过签名来进行post操作。

data_wrap={'nonce':nonce,'key':key_value,'signature':signature}

js=requests.post(url,data=data_wrap).json()
 
如果直接按照上面的代码去获取账户相关信息或者去挂单的话,会返回104的签名错误。 经过不断的排查,发现是signature的字符格式的问题。
 
构造一个str转换格式的函数: def toHex(self,str):
lst =
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)这个函数的作用就是把原来十六进制格式的字符完全转化成十六进制,把前面的0x去掉,不足2位的补全为2位。
把经过处理的signature进行格式转换后,几次提交,终于发现可以获取到用户的账户信息,进行下单,撤单,等操作。
 
 
 
下面是一个获取账户信息的代码段: def getAccount(self):
url='https://www.jubi.com/api/v1/balance/'

nonce_value=self.get_nonce_time()
print nonce_value
key_value=self.public_key
private_key=self.private_key

s='nonce='+str(nonce_value)+'&'+'key='+key_value

print s

#signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.
md5=self.getHash(private_key)
print md5
print type(md5)

msg=bytes(s).encode('utf-8')
key=bytes(md5).encode('utf-8')
signature =hmac.new(key,msg,digestmod=hashlib.sha256).digest()
print signature
print type(signature)
sig=self.toHex(signature)

print sig
data_wrap={'nonce':nonce_value,'key':key_value,'signature':sig}

print data_wrap

data_en=urllib.urlencode(data_wrap)
req=urllib2.Request(url,data=data_en)
resp=urllib2.urlopen(req).read()
print resp


def toHex(self,str):
lst =
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)
 
以上的代码运行后返回一下账户信息:{"uid":123456,"nameauth":1,"moflag":1,"asset":,"btc_balance":0,"btc_lock":0,"drk_balance":0,"drk_lock":0,"blk_balance":0,"blk_lock":0,"vrc_balance":0,"vrc_lock":0,"tfc_balance":0,"tfc_lock":0,"jbc_balance":0,"jbc_lock":0,"ltc_balance":0,"ltc_lock":0,"doge_balance":0,"doge_lock":0,"xpm_balance":0,"xpm_lock":0,"ppc_balance":0,"ppc_lock":0,"wdc_balance":0,"wdc_lock":0,"vtc_balance":0,"vtc_lock":0,"max_balance":0,"max_lock":0,"ifc_balance":0,"ifc_lock":0,"zcc_balance":0,"zcc_lock":0,"zet_balance":0,"zet_lock":0,"eac_balance":0,"eac_lock":0,"fz_balance":0,"fz_lock":0,"skt_balance":0,"skt_lock":0,"plc_balance":0,"plc_lock":0,"mtc_balance":0,"mtc_lock":0,"qec_balance":0,"qec_lock":0,"lkc_balance":10,"lkc_lock":0,"met_balance":0,"met_lock":0,"ytc_balance":0,"ytc_lock":0,"hlb_balance":0,"hlb_lock":0,"game_balance":0,"game_lock":0,"rss_balance":0,"rss_lock":0,"rio_balance":0,"rio_lock":0,"ktc_balance":0,"ktc_lock":0,"pgc_balance":0,"pgc_lock":0,"mryc_balance":0,"mryc_lock":0,"eth_balance":0,"eth_lock":0,"etc_balance":0,"etc_lock":0,"dnc_balance":0,"dnc_lock":0,"gooc_balance":0,"gooc_lock":0,"xrp_balance":0,"xrp_lock":0,"nxt_balance":0,"nxt_lock":0,"lsk_balance":0,"lsk_lock":0,"xas_balance":0,"xas_lock":0,"peb_balance":0,"peb_lock":0,"nhgh_balance":0,"nhgh_lock":0,"xsgs_balance":0,"xsgs_lock":0,"ans_balance":0,"ans_lock":0,"bts_balance":0,"bts_lock":0,"cny_balance":0,"cny_lock":0}











 
聚币网个人邀请码:
514330
 
还没注册可以拿去用,对于我而言可以拿到你们交易费用的50%,不过一般交易费除非是超级大户,一般散户都很少。千分之一的交易手续费。
 
欢迎一起讨论:
Email:weigesysu@qq.com

 原创内容,转载请注明出处
http://30daydo.com/article/181 
  查看全部
******* 2018.14 更新 ***********
现在聚币网已经被关闭了,但是所有的币都可以转移到CoinEgg网了,币种和以前一模一样,只是用户参与度减少了很多,市场不是一个有效的市场,但是这对于操盘手来说,更加是一个收益大的地方。
使用下面链接注册后,用户可以返30%的佣金。 其实也无所谓,佣金不会很多,一次也就几分钱到几毛钱,自己去官网注册也可以。看个人心情啦。
 
http://www.coinegg.com/user/register?inv=7d91a
 
 后续会就coinegg写一个自动交易的系统出来
 

******* 8.28 更新 ***********
不少人反应签名不通过,经过调试,发现是加密前的字符拼接的顺序问题,这个拼接顺序要和你post上去的顺序要一致,才能通过。如果出现104的返回代码,说明是你的顺序问题,说明你的签名没有成功。
 
贴代码说明下: 使用字典循环,就可以知道正确的拼接顺序。 下面的代码是获取成交订单的。
    def Trade_list(self, coin):
'''
Trade_list(挂单查询)
您指定时间后的挂单,可以根据类型查询,比如查看正在挂单和全部挂单
Path:/api/v1/trade_list/
Request类型:POST
参数
key - API key
signature - signature
nonce - nonce
since - unix timestamp(utc timezone) default == 0, i.e. 返回所有
coin - 币种简称,例如btc、ltc、xas
type - 挂单类型[open:正在挂单, all:所有挂单]

返回JSON dictionary
id - 挂单ID
datetime - date and time
type - "buy" or "sell"
price - price
amount_original - 下单时数量
amount_outstanding - 当前剩余数量
'''
url = self.host + '/api/v1/trade_list/'
time.sleep(random.random())
nonce = self.get_nonce_time()
types = 'all'
since = 0
parameters = {'key': self.public_key, 'nonce': str(nonce), 'type': types, 'coin': coin, 'signature': ''}
# print parameters
post_data = ''
for k, v in parameters.items():
if not isinstance(v, str):
#if type(v) is not types.StringType:
v = str(v)
post_data = post_data + k
post_data = post_data + '=' + v + '&'

#print 'post-data:\n',post_data
post_data = post_data[:-1]
post_data = post_data.replace('&signature=', '')
#print post_data

signature = hmac.new(self.md5, post_data, digestmod=hashlib.sha256).digest()
sig = self.toHex(signature)
parameters['signature'] = sig
#print parameters
r = requests.post(url=url, data=parameters)
s = r.json()
#print s
return s

 
如果还是没有解决的话就网站内私信我看看问题所在。

******************************************* 原文内容 ***************************************************
 

 官方有API的文档,可是这个文档就像一个草稿一样,两个基本例子都没有。 所以自己摸索一下,自己写一个现成的例子给大家,可以有个参考。 下面的例子亲测成功。 
 
首先看一下官方的API文档:


一、API使用说明

1、请求过程说明

1.1 构造请求数据,用户数据按照Jubi提供的接口规则,通过程序生成签名和要传输给Jubi的数据集合;

1.2 发送请求数据,把构造完成的数据集合通过POST/GET提交的方式传递给Jubi;

1.3 Jubi对请求数据进行处理,服务器在接收到请求后,会首先进行安全校验,验证通过后便会处理该次发送过来的请求;

1.4 返回响应结果数据,Jubi把响应结果以JSON的格式反馈给用户,具体的响应格式,错误代码参见接口部分;

1.5 对获取的返回结果数据进行处理;

2、安全认证

所有的private API都需要经过认证

Api的申请可以到财务中心 -> API,申请得到私钥和公钥,私钥Jubi将不做储存,一旦丢失将无法找回

注意:请勿向任何人泄露这两个参数,这像您的密码一样重要

2.签名机制

每次请求private api 都需要验证签名,发送的参数示例:

$param = array(

amount => 1,

price => 10000,

type => 'buy',

nonce => 141377098123

key => 5zi7w-4mnes-swmc4-egg9b-f2iqw-396z4-g541b

signature => 459c69d25c496765191582d9611028b9974830e9dfafd762854669809290ed82

);

nonce 可以理解为一个递增的整数:http://zh.wikipedia.org/wiki/Nonce

key 是申请到的公钥

signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

 


 
 
  
首先聚币的行情是使用网络爬虫获取的,而说明中给出了一系列的参数,你需要做的就是把这些参数填充上去。
 
如果你只是想要获取行情,那么事情容易很多。
    def real_time_ticker(coin):
url = 'https://www.jubi.com/api/v1/ticker/'
try:
data = requests.post(url, data={'coin': coin}).json()

except Exception ,e:
print e
return data

上面代码展示的时候获取实时的行情。委一和买一的价格,数量,和当前成交的数量,价格。
 按照上面的格式,把参数coin填上去,比如要获取泽塔币, real_time_ticker('zet') 就会返回获取的数据。
{u'sell': u'0.179000', u'volume': 21828245.102822, u'buy': u'0.175010', u'last': u'0.179000', u'vol': 108290769.9171, u'high': u'0.289000', u'low': u'0.119141'}

 
 
所有的private API都需要经过认证, 就是说如果你要进行交易,委托,下单,你就需要使用私钥和公钥,并进行一系列的加密。


每次请求private api 都需要验证签名,发送的参数示例:

$param = array(

amount => 1,

price => 10000,

type => 'buy',

nonce => 141377098123

key => 5zi7w-4mnes-swmc4-egg9b-f2iqw-396z4-g541b

signature => 459c69d25c496765191582d9611028b9974830e9dfafd762854669809290ed82

);

nonce 可以理解为一个递增的整数:http://zh.wikipedia.org/wiki/Nonce

key 是申请到的公钥

signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.


 
 
比如下单:


Trade_add(下单)
Path:/api/v1/trade_add/
Request类型:POST
 
参数
key - API key
signature - signature
nonce - nonce
amount - 购买数量
price - 购买价格
type - 买单或者卖单
coin - 币种简称,例如btc、ltc、xas
id - 挂单ID
result - true(成功), false(失败)
{"result":true, "id":"11"}
 
返回JSON dictionary
id - 挂单ID
result - true(成功), false(失败)
 
返回结果示例:
{"result":true, "id":"11"}
 



首先解决nonce。
 
在维基百科中
在安全工程中,Nonce是一个在加密通信只能使用一次的数字。在认证协议中,它往往是一个随机或伪随机数,以避免重放攻击。Nonce也用于流密码以确保安全。如果需要使用相同的密钥加密一个以上的消息,就需要Nonce来确保不同的消息与该密钥加密的密钥流不同。
 
结合stackoverflow, nonce只是一个12位的随机数。
可以用以下方法获得这个随机数
    def get_nonce(self):
lens=12
return ''.join([str(random.randint(0, 9)) for i in range(lens)])

 聚币中的nonce的位数是12位,所以lens定义为12
 
或者可以直接用时间函数生成:
    def get_nonce_time(self):
lens = 12
curr_stamp = time.time()*100
nonece=int(curr_stamp)
return nonece

 
然后是signature。
signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

先把私钥进行md5处理
    def getHash(self,s):
m=hashlib.md5()
m.update(s)
return m.hexdigest()

只要把私钥传入函数getHash就可以得到一个md5处理过的字符串。
 
私钥是聚币网给每个用户分配的字符串,是唯一的,这里假设为private_key=123456789吧,具体是多少,在你的聚币网设置里面可以找到。
sha_256key=self.getHash(private_key)
 
按照要求吧 你要post的数据字符串连起来
nonce=self.get_nonce_time
type='buy'
amount='10000'
key='xxxxxxxxxxx‘ #这个是聚币网给你的公钥,同样在设置里头可以找到
price='10' #你要设置的价格为10
coin='zet'
message = "amount=“+amount+”&nonce="+str(nonce)+"&type="+type+"&key="+key+'&price="+price+"&coin"+coin

signature = hmac.new(sha_256key, message, digestmod=hashlib.sha256).digest()

这样获得signature之后,就可以通过签名来进行post操作。

data_wrap={'nonce':nonce,'key':key_value,'signature':signature}

js=requests.post(url,data=data_wrap).json()

 
如果直接按照上面的代码去获取账户相关信息或者去挂单的话,会返回104的签名错误。 经过不断的排查,发现是signature的字符格式的问题。
 
构造一个str转换格式的函数:
    def toHex(self,str):
lst =
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)
这个函数的作用就是把原来十六进制格式的字符完全转化成十六进制,把前面的0x去掉,不足2位的补全为2位。
把经过处理的signature进行格式转换后,几次提交,终于发现可以获取到用户的账户信息,进行下单,撤单,等操作。
 
 
 
下面是一个获取账户信息的代码段:
    def getAccount(self):
url='https://www.jubi.com/api/v1/balance/'

nonce_value=self.get_nonce_time()
print nonce_value
key_value=self.public_key
private_key=self.private_key

s='nonce='+str(nonce_value)+'&'+'key='+key_value

print s

#signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.
md5=self.getHash(private_key)
print md5
print type(md5)

msg=bytes(s).encode('utf-8')
key=bytes(md5).encode('utf-8')
signature =hmac.new(key,msg,digestmod=hashlib.sha256).digest()
print signature
print type(signature)
sig=self.toHex(signature)

print sig
data_wrap={'nonce':nonce_value,'key':key_value,'signature':sig}

print data_wrap

data_en=urllib.urlencode(data_wrap)
req=urllib2.Request(url,data=data_en)
resp=urllib2.urlopen(req).read()
print resp


def toHex(self,str):
lst =
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)

 
以上的代码运行后返回一下账户信息:
{"uid":123456,"nameauth":1,"moflag":1,"asset":,"btc_balance":0,"btc_lock":0,"drk_balance":0,"drk_lock":0,"blk_balance":0,"blk_lock":0,"vrc_balance":0,"vrc_lock":0,"tfc_balance":0,"tfc_lock":0,"jbc_balance":0,"jbc_lock":0,"ltc_balance":0,"ltc_lock":0,"doge_balance":0,"doge_lock":0,"xpm_balance":0,"xpm_lock":0,"ppc_balance":0,"ppc_lock":0,"wdc_balance":0,"wdc_lock":0,"vtc_balance":0,"vtc_lock":0,"max_balance":0,"max_lock":0,"ifc_balance":0,"ifc_lock":0,"zcc_balance":0,"zcc_lock":0,"zet_balance":0,"zet_lock":0,"eac_balance":0,"eac_lock":0,"fz_balance":0,"fz_lock":0,"skt_balance":0,"skt_lock":0,"plc_balance":0,"plc_lock":0,"mtc_balance":0,"mtc_lock":0,"qec_balance":0,"qec_lock":0,"lkc_balance":10,"lkc_lock":0,"met_balance":0,"met_lock":0,"ytc_balance":0,"ytc_lock":0,"hlb_balance":0,"hlb_lock":0,"game_balance":0,"game_lock":0,"rss_balance":0,"rss_lock":0,"rio_balance":0,"rio_lock":0,"ktc_balance":0,"ktc_lock":0,"pgc_balance":0,"pgc_lock":0,"mryc_balance":0,"mryc_lock":0,"eth_balance":0,"eth_lock":0,"etc_balance":0,"etc_lock":0,"dnc_balance":0,"dnc_lock":0,"gooc_balance":0,"gooc_lock":0,"xrp_balance":0,"xrp_lock":0,"nxt_balance":0,"nxt_lock":0,"lsk_balance":0,"lsk_lock":0,"xas_balance":0,"xas_lock":0,"peb_balance":0,"peb_lock":0,"nhgh_balance":0,"nhgh_lock":0,"xsgs_balance":0,"xsgs_lock":0,"ans_balance":0,"ans_lock":0,"bts_balance":0,"bts_lock":0,"cny_balance":0,"cny_lock":0}











 
聚币网个人邀请码:
514330
 
还没注册可以拿去用,对于我而言可以拿到你们交易费用的50%,不过一般交易费除非是超级大户,一般散户都很少。千分之一的交易手续费。
 
欢迎一起讨论:
Email:weigesysu@qq.com

 原创内容,转载请注明出处
http://30daydo.com/article/181 
 

python 计算当天指定某个时段的成交量

李魔佛 发表了文章 • 0 个评论 • 6915 次浏览 • 2017-05-08 23:32 • 来自相关话题

计算当天指定某个时段的成交量
 
为什么需要这个功能? 因为平时复盘的时候,会切换当天的分时图,一般喜欢切换成5分钟图,这样子就对每个时刻的成交量有比较直观的认识。比如今天(2017-05-08)的无锡银行。
 






很无耻是吧? 我就像看看尾盘的20分钟内,主力动用了多少资金把股价从水下直接拉到涨停。 用程序处理,比用手工计算,要节省多时间了(前阵子的确是每笔粗略的相加)。
 
只要在main()中修改股票代码和你要获取成交量的时间,就可以获取你想要的数据。 还有一个数据就是该成交量占当天成交量的比例。# -*-coding=utf-8-*-
__author__ = 'Rocky'
#计算某个股票的某个时间段的成交量
import tushare as ts
import pandas as pd
import datetime
pd.set_option('display.max_rows',None)
class amount_calculation():
def __init__(self,code):
self.df=ts.get_today_ticks(code)

#转换str为时间格式,便于下面用来比较时间的大小
self.df['time']=self.df['time'].map(lambda x:datetime.datetime.strptime(str(x),'%H:%M:%S'))
print '\n'
self.total= self.df['volume'].sum()

def calc(self,start,end):
s0=datetime.datetime.strptime(start,'%H:%M:%S')
e0=datetime.datetime.strptime(end,'%H:%M:%S')
new_df=self.df[(self.df['time']>=s0) & (self.df['time']<e0) ]
part=new_df['volume'].sum()
print part
rate=round(part*1.00/self.total*100,2)
print rate
return rate




def main():
obj=amount_calculation('600908')
#s1=obj.calc('09:24:00','10:30:00')
#s2=obj.calc('10:30:00','11:30:00')
#s3=obj.calc('13:00:00','14:00:00')
s4=obj.calc('14:35:00','15:05:00')
#print s1+s2+s3+s4

main()
 
运行上面代码,得到
 
114046
34.16
成交量为11.4万手,大概占当天成交量的34.16%, 半小时的时间。(1/8的时间,涨了1/3的成交量)
算出这个有什么用呢?
 
对于庄股,可以便于你计算出主力当天吸了多少货,或者出了多少货。 数据不会完全精确,但是能够知道交易的量级。 像上面的例子,大概就10w-12w手的样子。
 
更多文章
30天学会量化交易模型 Day01 查看全部
计算当天指定某个时段的成交量
 
为什么需要这个功能? 因为平时复盘的时候,会切换当天的分时图,一般喜欢切换成5分钟图,这样子就对每个时刻的成交量有比较直观的认识。比如今天(2017-05-08)的无锡银行。
 

无锡银行.PNG


很无耻是吧? 我就像看看尾盘的20分钟内,主力动用了多少资金把股价从水下直接拉到涨停。 用程序处理,比用手工计算,要节省多时间了(前阵子的确是每笔粗略的相加)。
 
只要在main()中修改股票代码和你要获取成交量的时间,就可以获取你想要的数据。 还有一个数据就是该成交量占当天成交量的比例。
# -*-coding=utf-8-*-
__author__ = 'Rocky'
#计算某个股票的某个时间段的成交量
import tushare as ts
import pandas as pd
import datetime
pd.set_option('display.max_rows',None)
class amount_calculation():
def __init__(self,code):
self.df=ts.get_today_ticks(code)

#转换str为时间格式,便于下面用来比较时间的大小
self.df['time']=self.df['time'].map(lambda x:datetime.datetime.strptime(str(x),'%H:%M:%S'))
print '\n'
self.total= self.df['volume'].sum()

def calc(self,start,end):
s0=datetime.datetime.strptime(start,'%H:%M:%S')
e0=datetime.datetime.strptime(end,'%H:%M:%S')
new_df=self.df[(self.df['time']>=s0) & (self.df['time']<e0) ]
part=new_df['volume'].sum()
print part
rate=round(part*1.00/self.total*100,2)
print rate
return rate




def main():
obj=amount_calculation('600908')
#s1=obj.calc('09:24:00','10:30:00')
#s2=obj.calc('10:30:00','11:30:00')
#s3=obj.calc('13:00:00','14:00:00')
s4=obj.calc('14:35:00','15:05:00')
#print s1+s2+s3+s4

main()

 
运行上面代码,得到
 
114046
34.16
成交量为11.4万手,大概占当天成交量的34.16%, 半小时的时间。(1/8的时间,涨了1/3的成交量)
算出这个有什么用呢?
 
对于庄股,可以便于你计算出主力当天吸了多少货,或者出了多少货。 数据不会完全精确,但是能够知道交易的量级。 像上面的例子,大概就10w-12w手的样子。
 
更多文章
30天学会量化交易模型 Day01

ts.get_stock_basics() to_excel("base.xls") 保存dataframe 编码错误

李魔佛 发表了文章 • 0 个评论 • 4615 次浏览 • 2017-04-21 18:36 • 来自相关话题

 
基本代码片:
base=ts.get_stock_basics()
base.to_csv('2.xls')
 出现的错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 1: ordinal not in range(128) 
然后替换几种编码方式:
base.to_excel('base.xls',encoding='GBK')
base.to_excel('111.xls',encoding='utf8')
base.to_excel('111.xls‘)
不过问题还在。
 
而保存为csv文件却没有这个编码问题:
 
base.to_csv('base.csv)
 
 
于是采取了迂回战术, 先把数据保存为csv, 然后读取这个文件,然后 再保存为exel文件。
 
居然给我弄成功了!!
 
  查看全部
 
基本代码片:
    base=ts.get_stock_basics()
base.to_csv('2.xls')

 出现的错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 1: ordinal not in range(128) 
然后替换几种编码方式:
    base.to_excel('base.xls',encoding='GBK')
base.to_excel('111.xls',encoding='utf8')
base.to_excel('111.xls‘)

不过问题还在。
 
而保存为csv文件却没有这个编码问题:
 
base.to_csv('base.csv)
 
 
于是采取了迂回战术, 先把数据保存为csv, 然后读取这个文件,然后 再保存为exel文件。
 
居然给我弄成功了!!
 
 

JoinQuant 遇到的问题总结 --定期更新

李魔佛 发表了文章 • 0 个评论 • 3241 次浏览 • 2017-04-20 23:51 • 来自相关话题

1. 一些涨停一字板的个股或者新股,你是无法买入的。 经过测试,会发现没有买入任何的个股。
1. 一些涨停一字板的个股或者新股,你是无法买入的。 经过测试,会发现没有买入任何的个股。

pandas dataframe 读取csv文件 数据类型转化 字符变成了数字

李魔佛 发表了文章 • 0 个评论 • 40211 次浏览 • 2017-04-17 22:43 • 来自相关话题

因为csv中包含了大量的股票代码,如果是002开头的股票,比如002111, 使用pd.read_csv('text.csv') 则会让所有的002xxx,变成了2xxx,前面2个0不见了,当然你可以收工操作,填充那2个0。 不过对于pandas大法,何须这么麻烦?
 
直接在参数一栏设置一下即可:
df=pd.read_csv('text.csv', dtype={'code':str}
 
这样,把你要转换的列的名字设定好, “code”列中的数据读取为str
 
这样,读取到的数据就是按照我们的要求的了。 查看全部
因为csv中包含了大量的股票代码,如果是002开头的股票,比如002111, 使用pd.read_csv('text.csv') 则会让所有的002xxx,变成了2xxx,前面2个0不见了,当然你可以收工操作,填充那2个0。 不过对于pandas大法,何须这么麻烦?
 
直接在参数一栏设置一下即可:
df=pd.read_csv('text.csv', dtype={'code':str}
 
这样,把你要转换的列的名字设定好, “code”列中的数据读取为str
 
这样,读取到的数据就是按照我们的要求的了。

tushare 中的ts.get_stock_basics() 函数总是超时 返回不到结果的原因

李魔佛 发表了文章 • 0 个评论 • 18023 次浏览 • 2017-04-17 18:30 • 来自相关话题

调用的方法:import tushare as ts

ts.get_stock_basics()
不过经常会出现: self.base=ts.get_stock_basics()
File "C:\Python27\lib\site-packages\tushare\stock\fundamental.py", line 44, in get_stock_basics
text = urlopen(request, timeout=10).read()
File "C:\Python27\lib\socket.py", line 351, in read
data = self._sock.recv(rbufsize)
File "C:\Python27\lib\httplib.py", line 567, in read
s = self.fp.read(amt)
File "C:\Python27\lib\socket.py", line 380, in read
data = self._sock.recv(left)
socket.timeout: timed out这样的问题。
 
这个是因为tushare的作者把get_stock_basics()的信息文件保存在他自己的服务器。
这一点可以翻看源码就知道。 地址为: http://218.244.146.57/static/all.csv 
估计作者用的一般的服务器,所以一旦数据请求多了,你的IP也被服务器当做是DDOS攻击,屏蔽掉你的请求了。
 
所以如果你平时需要频繁调用这个函数,不如把这个文件下载到本地,然后使用函数 df=pd.read_csv('all.csv')
来得到你想要数据,这样一来,程序不会因为经常超时而中断,而且本地读取文件的数据很快。 这样会节约不少的时间。
 
 
 在最新的tushare这个问题得到了解决。已经换一个数据源了。
 
PS:好多小问题都可以通过更新最新的tushare版本来得到解决。

升级命令:pip install tushare --upgrade
  查看全部
调用的方法:
import tushare as ts

ts.get_stock_basics()

不过经常会出现:
    self.base=ts.get_stock_basics()
File "C:\Python27\lib\site-packages\tushare\stock\fundamental.py", line 44, in get_stock_basics
text = urlopen(request, timeout=10).read()
File "C:\Python27\lib\socket.py", line 351, in read
data = self._sock.recv(rbufsize)
File "C:\Python27\lib\httplib.py", line 567, in read
s = self.fp.read(amt)
File "C:\Python27\lib\socket.py", line 380, in read
data = self._sock.recv(left)
socket.timeout: timed out
这样的问题。
 
这个是因为tushare的作者把get_stock_basics()的信息文件保存在他自己的服务器。
这一点可以翻看源码就知道。 地址为: http://218.244.146.57/static/all.csv 
估计作者用的一般的服务器,所以一旦数据请求多了,你的IP也被服务器当做是DDOS攻击,屏蔽掉你的请求了。
 
所以如果你平时需要频繁调用这个函数,不如把这个文件下载到本地,然后使用函数 df=pd.read_csv('all.csv')
来得到你想要数据,这样一来,程序不会因为经常超时而中断,而且本地读取文件的数据很快。 这样会节约不少的时间。
 
 
 在最新的tushare这个问题得到了解决。已经换一个数据源了。
 
PS:好多小问题都可以通过更新最新的tushare版本来得到解决。

升级命令:
pip install tushare --upgrade

 

中国各个省份/直辖市拥有的上市公司数目 附python代码

李魔佛 发表了文章 • 0 个评论 • 6358 次浏览 • 2017-04-16 02:25 • 来自相关话题

一个省份地区的上市公司的数目,可以很直接地反应这个地区的发达程度。
下面通过代码来统计这个数据, 其实很简单,用python只需几行代码就能够实现
  def count_area():
base=ts.get_stock_basics()
count=base['area'].value_counts()
#这一句的意思,就是获取所有股票的上市地区的数据,然后计算出现的次数
print count
print type(count)
得出的是以下的数据:
浙江     360
江苏     337
北京     289
广东     267
上海     251
深圳     242
山东     176
福建     116
四川     110
安徽      98
湖北      95
湖南      91
河南      76
辽宁      75
河北      54
新疆      50
天津      46
陕西      46
重庆      45
吉林      42
山西      38
江西      37
广西      36
黑龙江     35
云南      32
甘肃      31
海南      29
内蒙      25
贵州      23
西藏      14
宁夏      12
青海      11
 
从数据来看,数量最多的是江浙一带(因为深圳从广东省的数据中分离出去了)。
这个也从正面反映每个地方的经济繁荣程度。 查看全部
一个省份地区的上市公司的数目,可以很直接地反应这个地区的发达程度。
下面通过代码来统计这个数据, 其实很简单,用python只需几行代码就能够实现
 
    def count_area():
base=ts.get_stock_basics()
count=base['area'].value_counts()
#这一句的意思,就是获取所有股票的上市地区的数据,然后计算出现的次数
print count
print type(count)

得出的是以下的数据:
浙江     360
江苏     337
北京     289
广东     267
上海     251
深圳     242
山东     176
福建     116
四川     110
安徽      98
湖北      95
湖南      91
河南      76
辽宁      75
河北      54
新疆      50
天津      46
陕西      46
重庆      45
吉林      42
山西      38
江西      37
广西      36
黑龙江     35
云南      32
甘肃      31
海南      29
内蒙      25
贵州      23
西藏      14
宁夏      12
青海      11
 
从数据来看,数量最多的是江浙一带(因为深圳从广东省的数据中分离出去了)。
这个也从正面反映每个地方的经济繁荣程度。

mac os x python安装matplotlib 库 出错: Operation not permitted

低调的哥哥 发表了文章 • 0 个评论 • 8505 次浏览 • 2017-04-15 23:19 • 来自相关话题

使用pip安装: sudo pip install matplotlibPassword:
The directory '/Users/rocky/Library/Caches/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/Users/rocky/Library/Caches/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Requirement already satisfied: matplotlib in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python
Requirement already satisfied: numpy>=1.5 in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from matplotlib)
Requirement already satisfied: python-dateutil in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from matplotlib)
Collecting tornado (from matplotlib)
Downloading tornado-4.4.3.tar.gz (463kB)
100% |████████████████████████████████| 471kB 84kB/s
Requirement already satisfied: pyparsing>=1.5.6 in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from matplotlib)
Collecting nose (from matplotlib)
Downloading nose-1.3.7-py2-none-any.whl (154kB)
100% |████████████████████████████████| 163kB 75kB/s
Collecting singledispatch (from tornado->matplotlib)
Downloading singledispatch-3.4.0.3-py2.py3-none-any.whl
Collecting certifi (from tornado->matplotlib)
Downloading certifi-2017.1.23-py2.py3-none-any.whl (382kB)
100% |████████████████████████████████| 389kB 105kB/s
Collecting backports_abc>=0.4 (from tornado->matplotlib)
Downloading backports_abc-0.5-py2.py3-none-any.whl
Requirement already satisfied: six in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from singledispatch->tornado->matplotlib)
Installing collected packages: singledispatch, certifi, backports-abc, tornado, nose
Running setup.py install for tornado ... done
Exception:
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/pip/basecommand.py", line 215, in main
status = self.run(options, args)
File "/Library/Python/2.7/site-packages/pip/commands/install.py", line 342, in run
prefix=options.prefix_path,
File "/Library/Python/2.7/site-packages/pip/req/req_set.py", line 784, in install
**kwargs
File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 851, in install
self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 1064, in move_wheel_files
isolated=self.isolated,
File "/Library/Python/2.7/site-packages/pip/wheel.py", line 377, in move_wheel_files
clobber(source, dest, False, fixer=fixer, filter=filter)
File "/Library/Python/2.7/site-packages/pip/wheel.py", line 316, in clobber
ensure_dir(destdir)
File "/Library/Python/2.7/site-packages/pip/utils/__init__.py", line 83, in ensure_dir
os.makedirs(path)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 150, in makedirs
makedirs(head, mode)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 157, in makedirs
mkdir(name, mode)
OSError: [Errno 1] Operation not permitted: '/System/Library/Frameworks/Python.framework/Versions/2.7/man' 
分析了原因后,以为权限不够,所以就把这个目录:
/Users/rocky/Library/Caches/pip/
做了提权: sudo /Users/rocky/Library/Caches/pip/
然后重新运行sudo pip install matplotlib
然后没有上面提示的错误。 然后在主程序中继续运行,结果还是出现:matplotlib模块没找到。
 
删除后重装,问题依然存在。
 
于是尝试用easy_install 安装, sudo easy_install matplotlib
 
等待了大概10多分钟,居然安装成功了。 因为下载的服务器比较慢,所以等待的时间就有点长了。
  查看全部
使用pip安装: sudo pip install matplotlib
Password:
The directory '/Users/rocky/Library/Caches/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/Users/rocky/Library/Caches/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Requirement already satisfied: matplotlib in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python
Requirement already satisfied: numpy>=1.5 in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from matplotlib)
Requirement already satisfied: python-dateutil in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from matplotlib)
Collecting tornado (from matplotlib)
Downloading tornado-4.4.3.tar.gz (463kB)
100% |████████████████████████████████| 471kB 84kB/s
Requirement already satisfied: pyparsing>=1.5.6 in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from matplotlib)
Collecting nose (from matplotlib)
Downloading nose-1.3.7-py2-none-any.whl (154kB)
100% |████████████████████████████████| 163kB 75kB/s
Collecting singledispatch (from tornado->matplotlib)
Downloading singledispatch-3.4.0.3-py2.py3-none-any.whl
Collecting certifi (from tornado->matplotlib)
Downloading certifi-2017.1.23-py2.py3-none-any.whl (382kB)
100% |████████████████████████████████| 389kB 105kB/s
Collecting backports_abc>=0.4 (from tornado->matplotlib)
Downloading backports_abc-0.5-py2.py3-none-any.whl
Requirement already satisfied: six in /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python (from singledispatch->tornado->matplotlib)
Installing collected packages: singledispatch, certifi, backports-abc, tornado, nose
Running setup.py install for tornado ... done
Exception:
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/pip/basecommand.py", line 215, in main
status = self.run(options, args)
File "/Library/Python/2.7/site-packages/pip/commands/install.py", line 342, in run
prefix=options.prefix_path,
File "/Library/Python/2.7/site-packages/pip/req/req_set.py", line 784, in install
**kwargs
File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 851, in install
self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
File "/Library/Python/2.7/site-packages/pip/req/req_install.py", line 1064, in move_wheel_files
isolated=self.isolated,
File "/Library/Python/2.7/site-packages/pip/wheel.py", line 377, in move_wheel_files
clobber(source, dest, False, fixer=fixer, filter=filter)
File "/Library/Python/2.7/site-packages/pip/wheel.py", line 316, in clobber
ensure_dir(destdir)
File "/Library/Python/2.7/site-packages/pip/utils/__init__.py", line 83, in ensure_dir
os.makedirs(path)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 150, in makedirs
makedirs(head, mode)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 157, in makedirs
mkdir(name, mode)
OSError: [Errno 1] Operation not permitted: '/System/Library/Frameworks/Python.framework/Versions/2.7/man'
 
分析了原因后,以为权限不够,所以就把这个目录:
/Users/rocky/Library/Caches/pip/
做了提权: sudo /Users/rocky/Library/Caches/pip/
然后重新运行sudo pip install matplotlib
然后没有上面提示的错误。 然后在主程序中继续运行,结果还是出现:matplotlib模块没找到。
 
删除后重装,问题依然存在。
 
于是尝试用easy_install 安装, sudo easy_install matplotlib
 
等待了大概10多分钟,居然安装成功了。 因为下载的服务器比较慢,所以等待的时间就有点长了。
 

sqlite 删除数据库中重复的行

李魔佛 发表了文章 • 0 个评论 • 4754 次浏览 • 2017-03-21 18:34 • 来自相关话题

经常在爬取网络的信息后,会发现有重复的行。 如何使用sqlite删除那些重复的行?
 





 
本人SQL连入门都算不上,只能用到就去查相关的函数。
经过2个小时的不懈尝试,终于结合网上各种版本的删除数据重复行(网上太多坑呀 )
写出满足自己需求的sql语句
 
cmd='delete from STRATEGY where rowid not in (select max(rowid) from STRATEGY group by 代码);'
 
就是上面的这一句语句。
 
下面来简单说明一下,如果是DBA大牛请忽略。
 
首先表名字是STRATEGY,里面记录了一些股票,买入的原因,买入时间,股票名字和代码,当前股票的价格。当前的盈亏状态。
 
如果一天爬取同样的数据几次,机会自动追加到db数据中。 会造成大量的重复数据。 
首先从后面往前递推
 
select max(rowid) from STRATEGY group by 代码
 
这个语句 选择出来一些rowid, rowid是你创建数据库的时候默认就生产了,因为我在前面生成这个数据库的时候没有设置ID,或者index。 suo所以数据库默认用的是rowid,类似于行号。从第一行开始 rowid=1
 
上面就是 STRATEGY按照“代码”列进行排序, 因为有相同的,max(rowid) 
  查看全部
经常在爬取网络的信息后,会发现有重复的行。 如何使用sqlite删除那些重复的行?
 

重复.PNG

 
本人SQL连入门都算不上,只能用到就去查相关的函数。
经过2个小时的不懈尝试,终于结合网上各种版本的删除数据重复行(网上太多坑呀 )
写出满足自己需求的sql语句
 
cmd='delete from STRATEGY where rowid not in (select max(rowid) from STRATEGY group by 代码);'
 
就是上面的这一句语句。
 
下面来简单说明一下,如果是DBA大牛请忽略。
 
首先表名字是STRATEGY,里面记录了一些股票,买入的原因,买入时间,股票名字和代码,当前股票的价格。当前的盈亏状态。
 
如果一天爬取同样的数据几次,机会自动追加到db数据中。 会造成大量的重复数据。 
首先从后面往前递推
 
select max(rowid) from STRATEGY group by 代码
 
这个语句 选择出来一些rowid, rowid是你创建数据库的时候默认就生产了,因为我在前面生成这个数据库的时候没有设置ID,或者index。 suo所以数据库默认用的是rowid,类似于行号。从第一行开始 rowid=1
 
上面就是 STRATEGY按照“代码”列进行排序, 因为有相同的,max(rowid)