2015-01-07 01:26:14 +08:00
|
|
|
|
#!/usr/bin/python
|
|
|
|
|
# -*- coding: utf8 -*-
|
|
|
|
|
# cp936
|
2017-09-23 02:15:15 +08:00
|
|
|
|
#
|
|
|
|
|
# The MIT License (MIT)
|
|
|
|
|
#
|
|
|
|
|
# Copyright (c) 2010-2017 fasiondog
|
|
|
|
|
#
|
|
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
# in the Software without restriction, including without limitation the rights
|
|
|
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
# furnished to do so, subject to the following conditions:
|
|
|
|
|
#
|
|
|
|
|
# The above copyright notice and this permission notice shall be included in all
|
|
|
|
|
# copies or substantial portions of the Software.
|
|
|
|
|
#
|
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
|
# SOFTWARE.
|
|
|
|
|
|
|
|
|
|
__copyright__ = """
|
|
|
|
|
MIT License
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2010-2017 fasiondog
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
|
SOFTWARE.
|
2015-01-07 01:26:14 +08:00
|
|
|
|
"""
|
|
|
|
|
|
2020-06-25 15:59:37 +08:00
|
|
|
|
import urllib
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
import configparser
|
|
|
|
|
|
2020-06-26 21:39:53 +08:00
|
|
|
|
from .extend import *
|
2017-09-23 21:20:36 +08:00
|
|
|
|
|
2018-09-10 02:21:19 +08:00
|
|
|
|
__version__ = getVersion()
|
|
|
|
|
|
2020-06-25 15:59:37 +08:00
|
|
|
|
#重定向C++ stdout/stderr输出至python
|
|
|
|
|
#iodog = ostream_redirect()
|
|
|
|
|
iodog = OstreamRedirect()
|
|
|
|
|
iodog.open()
|
|
|
|
|
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
# 引入扯线木偶
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
# Puppet是一套以同花顺交易客户端为核心的完整的闭环实盘交易系统框架。
|
|
|
|
|
# 来自:"睿瞳深邃(https://github.com/Raytone-D" 感谢睿瞳深邃的大度共享 :-)
|
|
|
|
|
# 可以用:tm.regBroker(crtRB(Puppet())) 的方式注册进tm实例,实现实盘下单
|
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
|
from .puppet import *
|
|
|
|
|
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
#
|
|
|
|
|
# 读取配置信息,并初始化
|
|
|
|
|
#
|
|
|
|
|
# ==============================================================================
|
2020-07-04 00:15:54 +08:00
|
|
|
|
config_file = './test_data/hikyuu_win.ini'
|
|
|
|
|
#config_file = os.path.expanduser('~') + "/.hikyuu/hikyuu.ini"
|
2020-06-25 15:59:37 +08:00
|
|
|
|
if not os.path.exists(config_file):
|
|
|
|
|
# 检查老版本配置是否存在,如果存在可继续使用,否则异常终止
|
|
|
|
|
data_config_file = os.path.expanduser('~') + "/.hikyuu/data_dir.ini"
|
|
|
|
|
data_config = configparser.ConfigParser()
|
|
|
|
|
data_config.read(data_config_file)
|
|
|
|
|
data_dir = data_config['data_dir']['data_dir']
|
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
|
config_file = data_dir + "\\hikyuu_win.ini"
|
|
|
|
|
else:
|
|
|
|
|
config_file = data_dir + "/hikyuu_linux.ini"
|
|
|
|
|
if not os.path.exists(config_file):
|
|
|
|
|
raise ("未找到配置文件,请先使用数据导入工具导入数据(将自动生成配置文件)!!!")
|
|
|
|
|
|
|
|
|
|
ini = configparser.ConfigParser()
|
|
|
|
|
ini.read(config_file)
|
|
|
|
|
hku_param = Parameter()
|
|
|
|
|
hku_param.set("tmpdir", ini.get('hikyuu', 'tmpdir'))
|
|
|
|
|
if ini.has_option('hikyuu', 'logger'):
|
|
|
|
|
hku_param.set("logger", ini['hikyuu']['logger'])
|
|
|
|
|
|
|
|
|
|
base_param = Parameter()
|
|
|
|
|
base_info_config = ini.options('baseinfo')
|
|
|
|
|
for p in base_info_config:
|
|
|
|
|
base_param.set(p, ini.get('baseinfo', p))
|
|
|
|
|
|
|
|
|
|
block_param = Parameter()
|
|
|
|
|
block_config = ini.options('block')
|
|
|
|
|
for p in block_config:
|
|
|
|
|
block_param.set(p, ini.get('block', p))
|
|
|
|
|
|
|
|
|
|
preload_param = Parameter()
|
|
|
|
|
preload_config = ini.options('preload')
|
|
|
|
|
for p in preload_config:
|
|
|
|
|
# 注意:proload参数是布尔类型
|
|
|
|
|
preload_param.set(p, ini.getboolean('preload', p))
|
|
|
|
|
|
|
|
|
|
kdata_param = Parameter()
|
|
|
|
|
kdata_config = ini.options('kdata')
|
|
|
|
|
for p in kdata_config:
|
|
|
|
|
kdata_param.set(p, ini.get('kdata', p))
|
|
|
|
|
|
|
|
|
|
set_log_level(LOG_LEVEL.TRACE)
|
|
|
|
|
sm = StockManager.instance()
|
|
|
|
|
sm.init(base_param, block_param, kdata_param, preload_param, hku_param)
|
|
|
|
|
set_log_level(LOG_LEVEL.WARN)
|
|
|
|
|
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
#
|
|
|
|
|
# 引入blocka、blocksh、blocksz、blockg全局变量,便于交互式环境下使用
|
|
|
|
|
#
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
blocka = Block("A", "ALL")
|
|
|
|
|
for s in sm:
|
|
|
|
|
if s.type in (constant.STOCKTYPE_A, constant.STOCKTYPE_GEM):
|
|
|
|
|
blocka.add(s)
|
|
|
|
|
zsbk_a = blocka
|
|
|
|
|
|
|
|
|
|
blocksh = Block("A", "SH")
|
|
|
|
|
for s in blocka:
|
|
|
|
|
if s.market == "SH":
|
|
|
|
|
blocksh.add(s)
|
|
|
|
|
zsbk_sh = blocksh
|
|
|
|
|
|
|
|
|
|
blocksz = Block("A", "SZ")
|
|
|
|
|
for s in blocka:
|
|
|
|
|
if s.market == "SZ":
|
|
|
|
|
blocksz.add(s)
|
|
|
|
|
zsbk_sz = blocksz
|
|
|
|
|
|
|
|
|
|
blockg = Block("G", "创业板")
|
|
|
|
|
for s in sm:
|
|
|
|
|
if s.type == constant.STOCKTYPE_GEM:
|
|
|
|
|
blockg.add(s)
|
|
|
|
|
zsbk_cyb = blockg
|
|
|
|
|
|
|
|
|
|
blockzxb = Block("A", "中小板")
|
|
|
|
|
for s in blocksz:
|
|
|
|
|
if s.code[:3] == "002":
|
|
|
|
|
blockzxb.add(s)
|
|
|
|
|
zsbk_zxb = blockzxb
|
|
|
|
|
|
|
|
|
|
zsbk_sz50 = sm.getBlock("指数板块", "上证50")
|
|
|
|
|
zsbk_sz180 = sm.getBlock("指数板块", "上证180")
|
|
|
|
|
zsbk_hs300 = sm.getBlock("指数板块", "沪深300")
|
|
|
|
|
zsbk_zz100 = sm.getBlock("指数板块", "沪深300")
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
# 重定义Query
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
Query.INDEX = Query.QueryType.INDEX
|
|
|
|
|
Query.DATE = Query.QueryType.DATE
|
|
|
|
|
Query.DAY = "DAY"
|
|
|
|
|
Query.WEEK = "WEEK"
|
|
|
|
|
Query.MONTH = "MONTH"
|
|
|
|
|
Query.QUARTER = "QUARTER"
|
|
|
|
|
Query.HALFYEAR = "HALFYEAR"
|
|
|
|
|
Query.YEAR = "YEAR"
|
|
|
|
|
Query.MIN = "MIN"
|
|
|
|
|
Query.MIN5 = "MIN5"
|
|
|
|
|
Query.MIN15 = "MIN15"
|
|
|
|
|
Query.MIN30 = "MIN30"
|
|
|
|
|
Query.MIN60 = "MIN60"
|
|
|
|
|
Query.HOUR2 = "HOUR2"
|
|
|
|
|
Query.HOUR4 = "HOUR4"
|
|
|
|
|
Query.HOUR6 = "HOUR6"
|
|
|
|
|
Query.HOUR12 = "HOUR12"
|
|
|
|
|
Query.NO_RECOVER = Query.RecoverType.NO_RECOVER
|
|
|
|
|
Query.FORWARD = Query.RecoverType.FORWARD
|
|
|
|
|
Query.BACKWARD = Query.RecoverType.BACKWARD
|
|
|
|
|
Query.EQUAL_FORWARD = Query.RecoverType.EQUAL_FORWARD
|
|
|
|
|
Query.EQUAL_BACKWARD = Query.RecoverType.EQUAL_BACKWARD
|
|
|
|
|
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
#
|
|
|
|
|
# 设置关键类型简称
|
|
|
|
|
#
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
O = OPEN()
|
|
|
|
|
C = CLOSE()
|
|
|
|
|
H = HIGH()
|
|
|
|
|
L = LOW()
|
|
|
|
|
A = AMO()
|
|
|
|
|
V = VOL()
|
|
|
|
|
D = Datetime
|
|
|
|
|
K = None
|
|
|
|
|
Q = Query
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_global_context(stk, query):
|
|
|
|
|
"""设置全局的 context
|
|
|
|
|
|
|
|
|
|
:param Stock stk: 指定的全局Stock
|
|
|
|
|
:param Query query: 指定的查询条件
|
|
|
|
|
"""
|
|
|
|
|
global K, O, C, H, L, A, V
|
|
|
|
|
K = stk.getKData(query)
|
|
|
|
|
O.setContext(K)
|
|
|
|
|
C.setContext(K)
|
|
|
|
|
H.setContext(K)
|
|
|
|
|
L.setContext(K)
|
|
|
|
|
A.setContext(K)
|
|
|
|
|
V.setContext(K)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_global_context():
|
|
|
|
|
"""获取当前的全局上下文
|
|
|
|
|
|
|
|
|
|
:rtype: KData
|
|
|
|
|
"""
|
|
|
|
|
return C.getContext()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_global_context(sm['sh000001'], Query(-150))
|
|
|
|
|
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
#
|
|
|
|
|
# 设置默认绘图引擎
|
|
|
|
|
#
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
from .draw import *
|
|
|
|
|
use_draw_engine('matplotlib')
|
|
|
|
|
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
#
|
|
|
|
|
# 粗略的选股函数
|
|
|
|
|
#
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def select(cond, start=Datetime(201801010000), end=Datetime.now(), print_out=True):
|
|
|
|
|
"""
|
|
|
|
|
示例:
|
|
|
|
|
#选出涨停股
|
|
|
|
|
C = CLOSE()
|
|
|
|
|
x = select(C / REF(C, 1) - 1 >= 0.0995))
|
|
|
|
|
|
|
|
|
|
:param Indicator cond: 条件指标
|
|
|
|
|
:param Datetime start: 起始日期
|
|
|
|
|
:param Datetime end: 结束日期
|
|
|
|
|
:param bool print_out: 打印选中的股票
|
|
|
|
|
:rtype: 选中的股票列表
|
|
|
|
|
"""
|
|
|
|
|
q = QueryByDate(start, end)
|
|
|
|
|
d = sm.getTradingCalendar(q, 'SH')
|
|
|
|
|
if len(d) == 0:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
result = []
|
|
|
|
|
for s in blocka:
|
|
|
|
|
if not s.valid:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
q = QueryByDate(start, end)
|
|
|
|
|
k = s.getKData(q)
|
|
|
|
|
cond.setContext(k)
|
|
|
|
|
if len(cond) > 0 and cond[-1] != constant.null_price and cond[-1] > 0 and len(k) > 0 and k[
|
|
|
|
|
-1].datetime == d[-1]:
|
|
|
|
|
result.append(s)
|
|
|
|
|
if print_out:
|
|
|
|
|
print(d[-1], s)
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
#
|
|
|
|
|
# 增加临时的实时数据更新函数 realtimeUpdate
|
|
|
|
|
#
|
|
|
|
|
# ==============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def UpdateOneRealtimeRecord_from_sina(tmpstr):
|
|
|
|
|
try:
|
|
|
|
|
if len(tmpstr) > 3 and tmpstr[:3] == 'var':
|
|
|
|
|
a = tmpstr.split(',')
|
|
|
|
|
if len(a) < 9:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
open, close, high, low = float(a[1]), float(a[3]), float(a[4]), float(a[5])
|
|
|
|
|
transamount = float(a[9])
|
|
|
|
|
transcount = float(a[8])
|
|
|
|
|
|
|
|
|
|
d = Datetime(a[-3] + " 00")
|
|
|
|
|
temp = (open, high, low, close)
|
|
|
|
|
if 0 in temp:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
stockstr = a[0].split('=')
|
|
|
|
|
stock = sm[stockstr[0][-8:]]
|
|
|
|
|
|
|
|
|
|
record = KRecord()
|
|
|
|
|
record.datetime = d
|
|
|
|
|
record.openPrice = open
|
|
|
|
|
record.highPrice = high
|
|
|
|
|
record.lowPrice = low
|
|
|
|
|
record.closePrice = close
|
|
|
|
|
record.transAmount = transamount
|
|
|
|
|
record.transCount = transcount / 100
|
|
|
|
|
|
|
|
|
|
stock.realtimeUpdate(record)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(tmpstr)
|
|
|
|
|
print(e)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def UpdateOneRealtimeRecord_from_qq(tmpstr):
|
|
|
|
|
try:
|
|
|
|
|
if len(tmpstr) > 3 and tmpstr[:2] == 'v_':
|
|
|
|
|
a = tmpstr.split('~')
|
|
|
|
|
if len(a) < 9:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
open, close, high, low = float(a[5]), float(a[3]), float(a[33]), float(a[34])
|
|
|
|
|
transamount = float(a[36])
|
|
|
|
|
transcount = float(a[37])
|
|
|
|
|
|
|
|
|
|
d = Datetime(int(a[30][:8] + '0000'))
|
|
|
|
|
temp = (open, high, low, close)
|
|
|
|
|
if 0 in temp:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
stockstr = a[0].split('=')
|
|
|
|
|
stock = sm[stockstr[0][-8:]]
|
|
|
|
|
|
|
|
|
|
record = KRecord()
|
|
|
|
|
record.datetime = d
|
|
|
|
|
record.openPrice = open
|
|
|
|
|
record.highPrice = high
|
|
|
|
|
record.lowPrice = low
|
|
|
|
|
record.closePrice = close
|
|
|
|
|
record.transAmount = transamount
|
|
|
|
|
record.transCount = transcount / 100
|
|
|
|
|
|
|
|
|
|
stock.realtimeUpdate(record)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(tmpstr)
|
|
|
|
|
print(e)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def realtimePartUpdate_from_sina(queryStr):
|
|
|
|
|
result = urllib.request.urlopen(queryStr).read()
|
|
|
|
|
try:
|
|
|
|
|
result = result.decode('gbk')
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(result)
|
|
|
|
|
print(e)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
result = result.split('\n')
|
|
|
|
|
for tmpstr in result:
|
|
|
|
|
UpdateOneRealtimeRecord_from_sina(tmpstr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def realtimePartUpdate_from_qq(queryStr):
|
|
|
|
|
result = urllib.request.urlopen(queryStr).read()
|
|
|
|
|
try:
|
|
|
|
|
result = result.decode('gbk')
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(result)
|
|
|
|
|
print(e)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
result = result.split('\n')
|
|
|
|
|
for tmpstr in result:
|
|
|
|
|
UpdateOneRealtimeRecord_from_qq(tmpstr)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def realtimeUpdate_from_sina_qq(source):
|
|
|
|
|
if source == 'sina':
|
|
|
|
|
queryStr = "http://hq.sinajs.cn/list="
|
|
|
|
|
update_func = realtimePartUpdate_from_sina
|
|
|
|
|
max_size = 140
|
|
|
|
|
elif source == 'qq':
|
|
|
|
|
queryStr = "http://qt.gtimg.cn/q="
|
|
|
|
|
update_func = realtimePartUpdate_from_qq
|
|
|
|
|
max_size = 60
|
|
|
|
|
else:
|
|
|
|
|
print('Not support!')
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
urls = []
|
|
|
|
|
tmpstr = queryStr
|
|
|
|
|
for stock in sm:
|
|
|
|
|
if stock.valid and stock.type in (
|
|
|
|
|
constant.STOCKTYPE_A, constant.STOCKTYPE_INDEX, constant.STOCKTYPE_ETF,
|
|
|
|
|
constant.STOCKTYPE_GEM
|
|
|
|
|
):
|
|
|
|
|
tmpstr += ("%s,") % (stock.market_code.lower())
|
|
|
|
|
count = count + 1
|
|
|
|
|
if count >= max_size:
|
|
|
|
|
# urls.append(tmpstr)
|
|
|
|
|
update_func(tmpstr)
|
|
|
|
|
count = 0
|
|
|
|
|
tmpstr = queryStr
|
|
|
|
|
|
|
|
|
|
if tmpstr != queryStr:
|
|
|
|
|
# urls.append(tmpstr)
|
|
|
|
|
update_func(tmpstr)
|
|
|
|
|
|
|
|
|
|
# 不用并行,防止过快,ip被网站屏蔽
|
|
|
|
|
#from multiprocessing import Pool
|
|
|
|
|
#from multiprocessing.dummy import Pool as ThreadPool
|
|
|
|
|
#pool = ThreadPool()
|
|
|
|
|
# if source == 'sina':
|
|
|
|
|
# pool.map(realtimePartUpdate_from_sina, urls)
|
|
|
|
|
# else:
|
|
|
|
|
# pool.map(realtimePartUpdate_from_qq, urls)
|
|
|
|
|
# pool.close()
|
|
|
|
|
# pool.join()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def realtimeUpdate_from_tushare():
|
|
|
|
|
import tushare as ts
|
|
|
|
|
|
|
|
|
|
# 更新股票行情
|
|
|
|
|
df = ts.get_today_all()
|
|
|
|
|
for i in range(len(df)):
|
|
|
|
|
if df.ix[i, 'open'] == 0:
|
|
|
|
|
continue # 停牌
|
|
|
|
|
|
|
|
|
|
code = df.ix[i][0]
|
|
|
|
|
stock = getStock('sh' + code)
|
|
|
|
|
|
|
|
|
|
if stock.isNull() == True or stock.type != constant.STOCKTYPE_A:
|
|
|
|
|
stock = getStock('sz' + code)
|
|
|
|
|
if stock.isNull() == True:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
record = KRecord()
|
|
|
|
|
record.openPrice = df.ix[i, 'open']
|
|
|
|
|
record.highPrice = df.ix[i, 'high']
|
|
|
|
|
record.lowPrice = df.ix[i, 'low']
|
|
|
|
|
record.closePrice = df.ix[i, 'trade']
|
|
|
|
|
record.transAmount = float(df.ix[i, 'amount'])
|
|
|
|
|
record.transCount = float(df.ix[i, 'volume'])
|
|
|
|
|
|
|
|
|
|
from datetime import date
|
|
|
|
|
d = date.today()
|
|
|
|
|
record.datetime = Datetime(d)
|
|
|
|
|
stock.realtimeUpdate(record)
|
|
|
|
|
|
|
|
|
|
# 更新指数行情
|
|
|
|
|
df = ts.get_index()
|
|
|
|
|
for i in range(len(df)):
|
|
|
|
|
code = df.ix[i][0]
|
|
|
|
|
stock = getStock('sh' + code)
|
|
|
|
|
if stock.isNull() == True or stock.type != constant.STOCKTYPE_INDEX:
|
|
|
|
|
stock = getStock('sz' + code)
|
|
|
|
|
if stock.isNull() == True:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
total = stock.getCount(Query.DAY)
|
|
|
|
|
if total == 0:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
last_record = stock.getKRecord(total - 1)
|
|
|
|
|
|
|
|
|
|
record = KRecord()
|
|
|
|
|
record.openPrice = df.ix[i, 'open']
|
|
|
|
|
record.highPrice = df.ix[i, 'high']
|
|
|
|
|
record.lowPrice = df.ix[i, 'low']
|
|
|
|
|
record.closePrice = df.ix[i, 'close']
|
|
|
|
|
record.transCount = float(df.ix[i, 'volume'])
|
|
|
|
|
record.transAmount = float(df.ix[i, 'amount'])
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
last_record.closePrice != record.closePrice or last_record.highPrice != record.highPrice
|
|
|
|
|
or last_record.lowPrice != record.lowPrice or last_record.openPrice != record.openPrice
|
|
|
|
|
):
|
|
|
|
|
from datetime import date
|
|
|
|
|
d = date.today()
|
|
|
|
|
record.datetime = Datetime(d)
|
|
|
|
|
stock.realtimeUpdate(record)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def realtimeUpdate_inner(source='tushare'):
|
|
|
|
|
if source == 'sina' or source == 'qq':
|
|
|
|
|
realtimeUpdate_from_sina_qq(source)
|
|
|
|
|
elif source == 'tushare':
|
|
|
|
|
realtimeUpdate_from_tushare()
|
|
|
|
|
else:
|
|
|
|
|
print(source, ' not support!')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def realtimeUpdateWrap():
|
|
|
|
|
pre_update_time = None
|
|
|
|
|
|
|
|
|
|
def realtimeUpdate_closure(source='tushare', delta=60):
|
|
|
|
|
"""
|
|
|
|
|
更新实时日线数据
|
|
|
|
|
参数:
|
|
|
|
|
source: 数据源('sina' | 'qq' | 'tushare')
|
|
|
|
|
delta: 更新间隔时间
|
|
|
|
|
"""
|
|
|
|
|
from datetime import timedelta, datetime
|
|
|
|
|
nonlocal pre_update_time
|
|
|
|
|
now_update_time = datetime.now()
|
|
|
|
|
if (pre_update_time is
|
|
|
|
|
None) or (now_update_time - pre_update_time) > timedelta(0, delta, 0):
|
|
|
|
|
realtimeUpdate_inner(source)
|
|
|
|
|
pre_update_time = datetime.now()
|
|
|
|
|
print("更新完毕!", pre_update_time)
|
|
|
|
|
else:
|
|
|
|
|
print("更新间隔小于" + str(delta) + "秒,未更新")
|
|
|
|
|
print("上次更新时间: ", pre_update_time)
|
|
|
|
|
|
|
|
|
|
return realtimeUpdate_closure
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
realtimeUpdate = realtimeUpdateWrap()
|