mirror of
https://gitee.com/fasiondog/hikyuu.git
synced 2024-12-03 12:27:48 +08:00
commit
85ba33c817
3
.gitignore
vendored
3
.gitignore
vendored
@ -13,6 +13,8 @@
|
||||
*.dll
|
||||
*.lib
|
||||
*.so
|
||||
*.so.*
|
||||
*.so.*.*
|
||||
*.dylib
|
||||
.metadata
|
||||
.settings
|
||||
@ -63,6 +65,7 @@ vs2015
|
||||
cover_report
|
||||
cover*.info
|
||||
*.gcno
|
||||
vsxmake*
|
||||
hikyuu/cpp/libhku_hdf5_cpp.so.200
|
||||
hikyuu/cpp/libhku_hdf5_cpp.so.200.2.0
|
||||
hikyuu/cpp/libhku_hdf5_hl_cpp.so.200
|
||||
|
@ -76,6 +76,13 @@ Linux下需安装依赖的开发软件包:hdf-dev、mysqlclient。如 Ubuntu
|
||||
.. code-block:: shell
|
||||
|
||||
sudo apt-get install -y libhdf5-dev libhdf5-serial-dev libmysqlclient-dev
|
||||
|
||||
6、转 Visual Studio 工程
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Windows 下,习惯用 msvc 调试的,可以使用 xmake project -k vsxmake -m "debug,release" 命令生成 VS 工程。命令执行后,会在当前目录下生成如 vsxmake2022 的子目录,VS工程位于其内。
|
||||
|
||||
在 VS 内,可以将 demo 设为启动工程,进行调试。
|
||||
|
||||
|
||||
编译与安装
|
||||
|
@ -1,6 +1,23 @@
|
||||
版本发布说明
|
||||
=======================
|
||||
|
||||
1.2.7 - 2022年11月21日
|
||||
-------------------------
|
||||
|
||||
fixed MySQL引擎只能导入数据,但实际无法使用
|
||||
|
||||
|
||||
1.2.6 - 2022年11月18日
|
||||
-------------------------
|
||||
|
||||
1. 新增发布 linux 下 pypi 包,linux 下也可以通过 pip install hikyuu 进行安装
|
||||
2. 获取股票代码表失败时增加保护
|
||||
3. 增加GUI异常保护
|
||||
4. fixed linux 下 mysql 数据库引擎报错(数据表名称都改为小写)
|
||||
5. fixed #I5YE01 bokeh_draw.py 鼠标滑动是的时间显示问题
|
||||
6. 优化系统策略延迟交易设置,将买入、卖出信号分开设置
|
||||
|
||||
|
||||
1.2.5 - 2022年9月3日
|
||||
-------------------------
|
||||
|
||||
|
@ -28,8 +28,8 @@
|
||||
|
||||
自定义移滑价差接口:
|
||||
|
||||
* :py:meth:`SlippageBase.getRealBuyPrice` - 【必须】计算实际买入价格
|
||||
* :py:meth:`SlippageBase.getRealSellPrice` - 【必须】计算实际卖出价格
|
||||
* :py:meth:`SlippageBase.get_real_buy_price` - 【必须】计算实际买入价格
|
||||
* :py:meth:`SlippageBase.get_real_sell_price` - 【必须】计算实际卖出价格
|
||||
* :py:meth:`SlippageBase._calculate` - 【必须】子类计算接口
|
||||
* :py:meth:`SlippageBase._clone` - 【必须】克隆接口
|
||||
* :py:meth:`SlippageBase._reset` - 【可选】重载私有变量
|
||||
|
@ -145,7 +145,14 @@ def update_hdf5_extern_data(h5file, tablename, data_type):
|
||||
else:
|
||||
newdate = olddate // 10000 * 10000 + 1500
|
||||
return newdate
|
||||
def getHour2Date(olddate):
|
||||
mint = olddate - olddate // 10000 * 10000
|
||||
if mint <= 1130:
|
||||
newdate = olddate // 10000 * 10000 + 1130
|
||||
else:
|
||||
newdate = olddate // 10000 * 10000 + 1500
|
||||
|
||||
return newdate
|
||||
def getMin15Date(olddate):
|
||||
mint = olddate - olddate // 10000 * 10000
|
||||
if mint <= 945:
|
||||
@ -219,13 +226,15 @@ def update_hdf5_extern_data(h5file, tablename, data_type):
|
||||
return getMin30Date(olddate)
|
||||
elif index_type == 'min60':
|
||||
return getMin60Date(olddate)
|
||||
elif index_type == 'hour2':
|
||||
return getHour2Date(olddate)
|
||||
else:
|
||||
return None
|
||||
|
||||
if data_type == 'DAY':
|
||||
index_list = ('week', 'month', 'quarter', 'halfyear', 'year')
|
||||
else:
|
||||
index_list = ('min15', 'min30', 'min60')
|
||||
index_list = ('min15', 'min30', 'min60', 'hour2')
|
||||
|
||||
groupDict = {}
|
||||
for index_type in index_list:
|
||||
|
@ -251,7 +251,16 @@ def update_extern_data(connect, market, code, data_type):
|
||||
startdate = newdate + 1401
|
||||
enddate = newdate + 1500
|
||||
return (startdate, enddate)
|
||||
|
||||
def getHour2Date(olddate):
|
||||
mint = olddate - olddate // 10000 * 10000
|
||||
newdate = olddate // 10000 * 10000
|
||||
if mint <= 1130:
|
||||
startdate = newdate + 931
|
||||
enddate = newdate + 1130
|
||||
else:
|
||||
startdate = newdate + 1301
|
||||
enddate = newdate + 1500
|
||||
return (startdate, enddate)
|
||||
def getMin15Date(olddate):
|
||||
mint = olddate - olddate // 10000 * 10000
|
||||
newdate = olddate // 10000 * 10000
|
||||
@ -351,6 +360,8 @@ def update_extern_data(connect, market, code, data_type):
|
||||
return getMin30Date(olddate)
|
||||
elif index_type == 'min60':
|
||||
return getMin60Date(olddate)
|
||||
elif index_type == 'hour2':
|
||||
return getHour2Date(olddate)
|
||||
else:
|
||||
return None
|
||||
|
||||
@ -359,7 +370,7 @@ def update_extern_data(connect, market, code, data_type):
|
||||
#index_list = ('week', 'month', 'quarter', 'halfyear', 'year')
|
||||
base_table = get_table(connect, market, code, 'day')
|
||||
else:
|
||||
index_list = ('min15', 'min30', 'min60')
|
||||
index_list = ('min15', 'min30', 'min60', 'hour2')
|
||||
#index_list = ('min15', )
|
||||
base_table = get_table(connect, market, code, 'min5')
|
||||
|
||||
|
@ -27,16 +27,16 @@ from concurrent import futures
|
||||
from pytdx.hq import TdxHq_API
|
||||
from pytdx.config.hosts import hq_hosts
|
||||
|
||||
hq_hosts = [
|
||||
('上海双线主站1', '47.103.48.45', 7709),
|
||||
('上海双线主站2', '47.103.86.229', 7709),
|
||||
('上海双线主站3', '47.103.88.146', 7709),
|
||||
('深圳双线主站1', '120.79.60.82', 7709),
|
||||
('深圳双线主站2', '47.112.129.66', 7709),
|
||||
('北京双线主站1', '39.98.234.173', 7709),
|
||||
('北京双线主站2', '39.98.198.249', 7709),
|
||||
('北京双线主站3', '39.100.68.59', 7709),
|
||||
]
|
||||
# hq_hosts = [
|
||||
# ('上海双线主站1', '47.103.48.45', 7709),
|
||||
# ('上海双线主站2', '47.103.86.229', 7709),
|
||||
# ('上海双线主站3', '47.103.88.146', 7709),
|
||||
# ('深圳双线主站1', '120.79.60.82', 7709),
|
||||
# ('深圳双线主站2', '47.112.129.66', 7709),
|
||||
# ('北京双线主站1', '39.98.234.173', 7709),
|
||||
# ('北京双线主站2', '39.98.198.249', 7709),
|
||||
# ('北京双线主站3', '39.100.68.59', 7709),
|
||||
# ]
|
||||
|
||||
|
||||
def to_pytdx_market(market):
|
||||
|
@ -48,6 +48,7 @@ min5 = {min5}
|
||||
min15 = {min15}
|
||||
min30 = {min30}
|
||||
min60 = {min60}
|
||||
hour2= {hour2}
|
||||
day_max = {day_max}
|
||||
week_max = {week_max}
|
||||
month_max = {month_max}
|
||||
@ -59,7 +60,7 @@ min5_max = {min5_max}
|
||||
min15_max = {min15_max}
|
||||
min30_max = {min30_max}
|
||||
min60_max = {min60_max}
|
||||
|
||||
hour2_max = {hour2_max}
|
||||
|
||||
[baseinfo]
|
||||
type = sqlite3
|
||||
@ -89,6 +90,7 @@ bj_trans = {dir}/bj_trans.h5
|
||||
mysql_template = """
|
||||
[hikyuu]
|
||||
tmpdir = {dir}
|
||||
datadir = {dir}
|
||||
|
||||
[block]
|
||||
type = qianlong
|
||||
@ -111,6 +113,7 @@ min5 = {min5}
|
||||
min15 = {min15}
|
||||
min30 = {min30}
|
||||
min60 = {min60}
|
||||
hour2 = {hour2}
|
||||
day_max = {day_max}
|
||||
week_max = {week_max}
|
||||
month_max = {month_max}
|
||||
@ -122,6 +125,7 @@ min5_max = {min5_max}
|
||||
min15_max = {min15_max}
|
||||
min30_max = {min30_max}
|
||||
min60_max = {min60_max}
|
||||
hour2_max = {hour2_max}
|
||||
|
||||
[baseinfo]
|
||||
type = mysql
|
||||
|
@ -8,6 +8,7 @@
|
||||
import requests
|
||||
import json
|
||||
import datetime
|
||||
import time
|
||||
from hikyuu.util import hku_warn, hku_info, hku_check
|
||||
|
||||
from .zhima import get_proxy
|
||||
@ -23,11 +24,13 @@ def request_with_proxy(url):
|
||||
proxy = get_proxy(new)
|
||||
hku_check(proxy, "Failed get proxy!")
|
||||
proxies = {'http': 'http://{}'.format(proxy)}
|
||||
result = requests.get(url, proxies=proxies).text
|
||||
result = requests.get(url, proxies=proxies, timeout=5).text
|
||||
#hku_info("use proxy: {}".format(proxies['http']))
|
||||
return result
|
||||
except:
|
||||
new = True
|
||||
except Exception as e:
|
||||
if i == 6:
|
||||
new = True
|
||||
time.sleep(2)
|
||||
raise Exception("无法通过代理访问!")
|
||||
|
||||
|
||||
|
@ -205,7 +205,7 @@ def get_spot_parallel(stocklist, source='sina', use_proxy=False, batch_func=None
|
||||
return batch_result
|
||||
|
||||
with futures.ThreadPoolExecutor() as executor:
|
||||
res = executor.map(request_inner, batchs, timeout=2)
|
||||
res = executor.map(request_inner, batchs, timeout=10)
|
||||
|
||||
result = []
|
||||
for batch_result in res:
|
||||
|
@ -93,16 +93,16 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
filename = self.getUserConfigDir() + '/importdata-gui.ini'
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
current_config.write(f)
|
||||
|
||||
filename = self.getHikyuuConfigFileName()
|
||||
if current_config.getboolean('hdf5', 'enable', fallback=True):
|
||||
data_dir = current_config['hdf5']['dir']
|
||||
if not os.path.lexists(data_dir + '/tmp'):
|
||||
os.mkdir(data_dir + '/tmp')
|
||||
|
||||
# 此处不能使用 utf-8 参数,否则导致Windows下getBlock无法找到板块分类
|
||||
# with open(filename, 'w', encoding='utf-8') as f:
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
|
||||
f.write(
|
||||
hku_config_template.hdf5_template.format(
|
||||
dir=data_dir,
|
||||
@ -117,6 +117,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
min15=current_config.getboolean('preload', 'min15', fallback=False),
|
||||
min30=current_config.getboolean('preload', 'min30', fallback=False),
|
||||
min60=current_config.getboolean('preload', 'min60', fallback=False),
|
||||
hour2=current_config.getboolean('preload', 'hour2', fallback=False),
|
||||
day_max=current_config.getint('preload', 'day_max', fallback=100000),
|
||||
week_max=current_config.getint('preload', 'week_max', fallback=100000),
|
||||
month_max=current_config.getint('preload', 'month_max', fallback=100000),
|
||||
@ -128,8 +129,10 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
min15_max=current_config.getint('preload', 'min15_max', fallback=4096),
|
||||
min30_max=current_config.getint('preload', 'min30_max', fallback=4096),
|
||||
min60_max=current_config.getint('preload', 'min60_max', fallback=4096),
|
||||
hour2_max=current_config.getint('preload', 'hour2_max', fallback=4096),
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
data_dir = current_config['mysql']['tmpdir']
|
||||
with open(filename, 'w') as f:
|
||||
@ -151,6 +154,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
min15=current_config.getboolean('preload', 'min15', fallback=False),
|
||||
min30=current_config.getboolean('preload', 'min30', fallback=False),
|
||||
min60=current_config.getboolean('preload', 'min60', fallback=False),
|
||||
hour2=current_config.getboolean('preload', 'hour2', fallback=False),
|
||||
day_max=current_config.getint('preload', 'day_max', fallback=100000),
|
||||
week_max=current_config.getint('preload', 'week_max', fallback=100000),
|
||||
month_max=current_config.getint('preload', 'month_max', fallback=100000),
|
||||
@ -162,6 +166,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
min15_max=current_config.getint('preload', 'min15_max', fallback=4096),
|
||||
min30_max=current_config.getint('preload', 'min30_max', fallback=4096),
|
||||
min60_max=current_config.getint('preload', 'min60_max', fallback=4096),
|
||||
hour2_max=current_config.getint('preload', 'hour2_max', fallback=4096),
|
||||
)
|
||||
)
|
||||
|
||||
@ -366,6 +371,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
self.preload_min15_checkBox.setChecked(import_config.getboolean('preload', 'min15', fallback=False))
|
||||
self.preload_min30_checkBox.setChecked(import_config.getboolean('preload', 'min30', fallback=False))
|
||||
self.preload_min60_checkBox.setChecked(import_config.getboolean('preload', 'min60', fallback=False))
|
||||
self.preload_hour2_checkBox.setChecked(import_config.getboolean('preload', 'hour2', fallback=False))
|
||||
self.preload_day_spinBox.setValue(import_config.getint('preload', 'day_max', fallback=100000))
|
||||
self.preload_week_spinBox.setValue(import_config.getint('preload', 'week_max', fallback=100000))
|
||||
self.preload_month_spinBox.setValue(import_config.getint('preload', 'month_max', fallback=100000))
|
||||
@ -377,6 +383,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
self.preload_min15_spinBox.setValue(import_config.getint('preload', 'min15_max', fallback=5120))
|
||||
self.preload_min30_spinBox.setValue(import_config.getint('preload', 'min30_max', fallback=5120))
|
||||
self.preload_min60_spinBox.setValue(import_config.getint('preload', 'min60_max', fallback=5120))
|
||||
self.preload_hour2_spinBox.setValue(import_config.getint('preload', 'hour2_max', fallback=5120))
|
||||
|
||||
def getCurrentConfig(self):
|
||||
import_config = ConfigParser()
|
||||
@ -441,6 +448,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
'min15': self.preload_min15_checkBox.isChecked(),
|
||||
'min30': self.preload_min30_checkBox.isChecked(),
|
||||
'min60': self.preload_min60_checkBox.isChecked(),
|
||||
'hour2': self.preload_hour2_checkBox.isChecked(),
|
||||
'day_max': self.preload_day_spinBox.value(),
|
||||
'week_max': self.preload_week_spinBox.value(),
|
||||
'month_max': self.preload_month_spinBox.value(),
|
||||
@ -452,6 +460,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
'min15_max': self.preload_min15_spinBox.value(),
|
||||
'min30_max': self.preload_min30_spinBox.value(),
|
||||
'min60_max': self.preload_min60_spinBox.value(),
|
||||
'hour2_max': self.preload_hour2_spinBox.value(),
|
||||
}
|
||||
return import_config
|
||||
|
||||
@ -654,7 +663,6 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
||||
or not os.path.isdir(config['tdx']['dir'])):
|
||||
QMessageBox.about(self, "错误", "请确认通达信安装目录是否正确!")
|
||||
return
|
||||
|
||||
try:
|
||||
self.saveConfig()
|
||||
except Exception as e:
|
||||
|
@ -458,6 +458,18 @@ class Ui_MainWindow(object):
|
||||
self.preload_min60_spinBox.setMaximum(999999)
|
||||
self.preload_min60_spinBox.setObjectName("preload_min60_spinBox")
|
||||
self.gridLayout_6.addWidget(self.preload_min60_spinBox, 10, 2, 1, 1)
|
||||
|
||||
self.preload_hour2_checkBox = QtWidgets.QCheckBox(self.layoutWidget4)
|
||||
self.preload_hour2_checkBox.setObjectName("preload_hour2_checkBox")
|
||||
self.gridLayout_6.addWidget(self.preload_hour2_checkBox, 11, 0, 1, 1)
|
||||
self.label_42 = QtWidgets.QLabel(self.layoutWidget4)
|
||||
self.label_42.setObjectName("label_42")
|
||||
self.gridLayout_6.addWidget(self.label_42, 11, 1, 1, 1)
|
||||
self.preload_hour2_spinBox = QtWidgets.QSpinBox(self.layoutWidget4)
|
||||
self.preload_hour2_spinBox.setMaximum(999999)
|
||||
self.preload_hour2_spinBox.setObjectName("preload_hour20_spinBox")
|
||||
self.gridLayout_6.addWidget(self.preload_hour2_spinBox, 11, 2, 1, 1)
|
||||
|
||||
self.layoutWidget5 = QtWidgets.QWidget(self.groupBox_6)
|
||||
self.layoutWidget5.setGeometry(QtCore.QRect(40, 30, 362, 40))
|
||||
self.layoutWidget5.setObjectName("layoutWidget5")
|
||||
@ -670,6 +682,8 @@ class Ui_MainWindow(object):
|
||||
self.label_33.setText(_translate("MainWindow", "最大缓存数量:"))
|
||||
self.preload_min60_checkBox.setText(_translate("MainWindow", "预加载60分钟线"))
|
||||
self.label_34.setText(_translate("MainWindow", "最大缓存数量:"))
|
||||
self.preload_hour2_checkBox.setText(_translate("MainWindow", "预加载2小时线"))
|
||||
self.label_42.setText(_translate("MainWindow", "最大缓存数量:"))
|
||||
self.label_35.setText(_translate("MainWindow", "此处为 Hikyuu 运行时的数据预加载设置,请根据机器内存大小选择"))
|
||||
self.label_36.setText(_translate("MainWindow", "(目前加载全部日线数据目前需要约需900M内存)"))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_6), _translate("MainWindow", "预加载设置"))
|
||||
|
@ -155,8 +155,8 @@ def next_delta(start_time, interval, phase1_delta, phase2_delta, ignore_weekend)
|
||||
elif maybe_time in (phase1_start, phase1_end, phase2_start, phase2_end):
|
||||
# 如果下一次时间刚好等于时间周期的起止点,则直接返回预计的时间间隔
|
||||
delta = interval_delta
|
||||
elif start_time < phase1_start and phase1_start < maybe_time < phase1_end:
|
||||
# 如果本次的时间小于周期1的起始时间且预计下一次的时间在phase1内,则取phase1起始时间计算
|
||||
elif start_time < phase1_start:
|
||||
# 如果本次的时间小于周期1的起始时间,则取phase1起始时间计算
|
||||
delta = phase1_start - start_time
|
||||
elif phase1_end < maybe_time < phase2_start:
|
||||
delta = phase2_start - start_time
|
||||
@ -271,7 +271,11 @@ def collect(use_proxy, source, seconds, phase1, phase2, ignore_weekend):
|
||||
#pub_sock.send('{}{}'.format(spot_topic, '[end spot]').encode('utf-8'))
|
||||
end_send_spot()
|
||||
delta = next_delta(start_time, seconds, phase1_delta, phase2_delta, ignore_weekend)
|
||||
time.sleep(delta.total_seconds())
|
||||
hku_info("sleep {}'s".format(delta.total_seconds()))
|
||||
if delta.total_seconds() > 0:
|
||||
time.sleep(delta.total_seconds())
|
||||
else:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
print("Ctrl-C 终止")
|
||||
break
|
||||
|
@ -111,7 +111,7 @@ for p in block_config:
|
||||
preload_param = Parameter()
|
||||
preload_config = ini.options('preload')
|
||||
for p in preload_config:
|
||||
if p in ('day', 'week', 'month', 'quarter', 'halfyear', 'year', 'min', 'min5', 'min15', 'min30', 'min60'):
|
||||
if p in ('day', 'week', 'month', 'quarter', 'halfyear', 'year', 'min', 'min5', 'min15', 'min30', 'min60', 'hour2'):
|
||||
preload_param[p] = ini.getboolean('preload', p)
|
||||
else:
|
||||
preload_param[p] = ini.getint('preload', p)
|
||||
|
@ -5,9 +5,7 @@
|
||||
* Author: fasiondog
|
||||
*/
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
#include <functional>
|
||||
#include "StockManager.h"
|
||||
#include "KDataImp.h"
|
||||
|
||||
@ -98,10 +96,10 @@ size_t KDataImp::getPos(const Datetime& datetime) {
|
||||
KRecordList::const_iterator iter;
|
||||
KRecord comp_record;
|
||||
comp_record.datetime = datetime;
|
||||
boost::function<bool(const KRecord&, const KRecord&)> f =
|
||||
boost::bind(&KRecord::datetime, _1) < boost::bind(&KRecord::datetime, _2);
|
||||
|
||||
iter = lower_bound(m_buffer.begin(), m_buffer.end(), comp_record, f);
|
||||
iter = lower_bound(
|
||||
m_buffer.begin(), m_buffer.end(), comp_record,
|
||||
std::bind(std::less<Datetime>(), std::bind(&KRecord::datetime, std::placeholders::_1),
|
||||
std::bind(&KRecord::datetime, std::placeholders::_2)));
|
||||
if (iter == m_buffer.end() || iter->datetime != datetime) {
|
||||
return Null<size_t>();
|
||||
}
|
||||
@ -180,7 +178,6 @@ void KDataImp::_recoverForward() {
|
||||
Datetime end_date(m_buffer.back().datetime.date() + bd::days(1));
|
||||
StockWeightList weightList = m_stock.getWeight(start_date, end_date);
|
||||
StockWeightList::const_iterator weightIter = weightList.begin();
|
||||
StockWeightList::const_iterator pre_weightIter = weightIter;
|
||||
|
||||
size_t pre_pos = 0;
|
||||
for (; weightIter != weightList.end(); ++weightIter) {
|
||||
|
@ -299,6 +299,10 @@ void Stock::loadKDataToBuffer(KQuery::KType inkType) {
|
||||
int start = total <= max_num ? 0 : total - max_num;
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock(*(m_data->pMutex[kType]));
|
||||
// 需要对是否已缓存进行二次判定,防止加锁之前已被缓存
|
||||
if (m_data->pKData.find(kType) != m_data->pKData.end() && m_data->pKData[kType]) {
|
||||
return;
|
||||
}
|
||||
KRecordList* ptr_klist = new KRecordList;
|
||||
m_data->pKData[kType] = ptr_klist;
|
||||
(*ptr_klist) = driver->getKRecordList(m_data->m_market, m_data->m_code,
|
||||
@ -585,7 +589,8 @@ KRecordList Stock::_getKRecordListFromBuffer(size_t start_ix, size_t end_ix,
|
||||
end_ix, total);
|
||||
size_t length = end_ix > total ? total - start_ix : end_ix - start_ix;
|
||||
result.resize(length);
|
||||
std::memcpy(&(result.front()), &((*m_data->pKData[ktype])[start_ix]), sizeof(KRecord) * length);
|
||||
std::memcpy((void*)&(result.front()), &((*m_data->pKData[ktype])[start_ix]),
|
||||
sizeof(KRecord) * length);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -714,6 +719,11 @@ void Stock::realtimeUpdate(KRecord record, KQuery::KType inktype) {
|
||||
// 加写锁
|
||||
std::unique_lock<std::shared_mutex> lock(*(m_data->pMutex[ktype]));
|
||||
|
||||
// 需要对是否已缓存进行二次判定,防止加锁之前缓存被释放
|
||||
if (m_data->pKData.find(ktype) == m_data->pKData.end() || !m_data->pKData[ktype]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_data->pKData[ktype]->empty()) {
|
||||
m_data->pKData[ktype]->push_back(record);
|
||||
return;
|
||||
|
@ -75,6 +75,7 @@ Parameter default_preload_param() {
|
||||
param.set<bool>("min15", false);
|
||||
param.set<bool>("min30", false);
|
||||
param.set<bool>("min60", false);
|
||||
param.set<bool>("hour2", false);
|
||||
param.set<bool>("ticks", false);
|
||||
param.set<int>("day_max", 100000);
|
||||
param.set<int>("week_max", 100000);
|
||||
@ -87,6 +88,7 @@ Parameter default_preload_param() {
|
||||
param.set<int>("min15_max", 5120);
|
||||
param.set<int>("min30_max", 5120);
|
||||
param.set<int>("min60_max", 5120);
|
||||
param.set<int>("hour2_max", 5120);
|
||||
param.set<int>("ticks_max", 5120);
|
||||
return param;
|
||||
}
|
||||
@ -191,6 +193,9 @@ void StockManager::setKDataDriver(const KDataDriverConnectPoolPtr& driver) {
|
||||
bool preload_min60 = m_preloadParam.tryGet<bool>("min60", false);
|
||||
HKU_INFO_IF(preload_min60, "Preloading all 60 min kdata to buffer!");
|
||||
|
||||
bool preload_hour2 = m_preloadParam.tryGet<bool>("hour2", false);
|
||||
HKU_INFO_IF(preload_hour2, "Preloading all 120 min kdata to buffer!");
|
||||
|
||||
if (!driver->getPrototype()->canParallelLoad()) {
|
||||
for (auto iter = m_stockDict.begin(); iter != m_stockDict.end(); ++iter) {
|
||||
if (iter->second.market() == "TMP")
|
||||
@ -218,6 +223,8 @@ void StockManager::setKDataDriver(const KDataDriverConnectPoolPtr& driver) {
|
||||
iter->second.loadKDataToBuffer(KQuery::MIN30);
|
||||
if (preload_min60)
|
||||
iter->second.loadKDataToBuffer(KQuery::MIN60);
|
||||
if (preload_hour2)
|
||||
iter->second.loadKDataToBuffer(KQuery::HOUR2);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -249,6 +256,8 @@ void StockManager::setKDataDriver(const KDataDriverConnectPoolPtr& driver) {
|
||||
tg.submit([=]() mutable { iter->second.loadKDataToBuffer(KQuery::MIN30); });
|
||||
if (preload_min60)
|
||||
tg.submit([=]() mutable { iter->second.loadKDataToBuffer(KQuery::MIN60); });
|
||||
if (preload_hour2)
|
||||
tg.submit([=]() mutable { iter->second.loadKDataToBuffer(KQuery::HOUR2); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ struct StockInfo {
|
||||
static const char* getSelectSQL() {
|
||||
return "select c.market, a.code, a.name, a.type, a.valid, a.startDate, a.endDate, b.tick, "
|
||||
"b.tickValue, b.precision, b.minTradeNumber, b.maxTradeNumber from stock a, "
|
||||
"StockTypeInfo b, market c where a.type = b.id and a.marketid = c.marketid";
|
||||
"stocktypeinfo b, market c where a.type = b.id and a.marketid = c.marketid";
|
||||
}
|
||||
|
||||
void load(const SQLStatementPtr& st) {
|
||||
|
@ -14,7 +14,7 @@
|
||||
namespace hku {
|
||||
|
||||
class HolidayTable {
|
||||
TABLE_BIND1(Holiday, date)
|
||||
TABLE_BIND1(holiday, date)
|
||||
|
||||
public:
|
||||
HolidayTable() : date(Datetime().number()) {}
|
||||
|
@ -77,21 +77,21 @@ private:
|
||||
|
||||
public:
|
||||
static const char* getInsertSQL() {
|
||||
return "insert into `Market` "
|
||||
return "insert into `market` "
|
||||
"(`marketid`, `market`, `name`, `description`, `code`, `lastDate`,"
|
||||
" `openTime1`, `closeTime1`, `openTime2`, `closeTime2`) "
|
||||
"values (?,?,?,?,?,?,?,?,?,?)";
|
||||
}
|
||||
|
||||
static const char* getUpdateSQL() {
|
||||
return "update `Market` set `market`=?, `name`=?, `description`=?, "
|
||||
return "update `market` set `market`=?, `name`=?, `description`=?, "
|
||||
"`code`=?, `lastDate`=?, `openTime1`=?, `closeTime1`=?, "
|
||||
"`openTime2=`=?, `closeTime2`=? where `marketid`=?";
|
||||
}
|
||||
|
||||
static const char* getSelectSQL() {
|
||||
return "select `marketid`,`market`,`name`, `description`, `code`, `lastDate`, "
|
||||
"`openTime1`, `closeTime1`, `openTime2`, `closeTime2` from `Market`";
|
||||
"`openTime1`, `closeTime1`, `openTime2`, `closeTime2` from `market`";
|
||||
}
|
||||
|
||||
void save(const SQLStatementPtr& st) const {
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace hku {
|
||||
|
||||
class StockWeightTable {
|
||||
TABLE_BIND9(stkWeight, stockid, date, countAsGift, countForSell, priceForSell, bonus,
|
||||
TABLE_BIND9(stkweight, stockid, date, countAsGift, countForSell, priceForSell, bonus,
|
||||
countOfIncreasement, totalCount, freeCount)
|
||||
|
||||
public:
|
||||
|
@ -125,6 +125,7 @@ bool H5KDataDriver::_init() {
|
||||
m_h5file_map[market + "_MIN15"] = h5file;
|
||||
m_h5file_map[market + "_MIN30"] = h5file;
|
||||
m_h5file_map[market + "_MIN60"] = h5file;
|
||||
m_h5file_map[market + "_HOUR2"] = h5file;
|
||||
|
||||
} else if (ktype == "TIME") {
|
||||
filename = getParam<string>(*iter);
|
||||
@ -233,6 +234,9 @@ bool H5KDataDriver::_getH5FileAndGroup(const string& market, const string& code,
|
||||
} else if (kType == KQuery::MIN60) {
|
||||
CHECK_GROUP_EXISTS_RET(out_file, "min60", false);
|
||||
out_group = out_file->openGroup("min60");
|
||||
} else if (kType == KQuery::HOUR2) {
|
||||
CHECK_GROUP_EXISTS_RET(out_file, "hour2", false);
|
||||
out_group = out_file->openGroup("hour2");
|
||||
} else if (kType == KQuery::DAY) {
|
||||
CHECK_GROUP_EXISTS_RET(out_file, "data", false);
|
||||
out_group = out_file->openGroup("data");
|
||||
@ -431,7 +435,7 @@ bool H5KDataDriver::_getOtherIndexRangeByDate(const string& market, const string
|
||||
assert(KQuery::WEEK == query.kType() || KQuery::MONTH == query.kType() ||
|
||||
KQuery::QUARTER == query.kType() || KQuery::HALFYEAR == query.kType() ||
|
||||
KQuery::YEAR == query.kType() || KQuery::MIN15 == query.kType() ||
|
||||
KQuery::MIN30 == query.kType() || KQuery::MIN60 == query.kType());
|
||||
KQuery::MIN30 == query.kType() || KQuery::MIN60 == query.kType() || KQuery::HOUR2 == query.kType());
|
||||
out_start = 0;
|
||||
out_end = 0;
|
||||
HKU_IF_RETURN(query.startDatetime() >= query.endDatetime(), false);
|
||||
|
@ -386,7 +386,7 @@ string TdxKDataDriver::_getFileName(const string& market, const string& code, KQ
|
||||
if (ktype == KQuery::MIN) {
|
||||
filename = m_dirname + "\\" + market + "\\minline\\" + market + code + ".lc1";
|
||||
} else if (ktype == KQuery::MIN5 || ktype == KQuery::MIN15 || ktype == KQuery::MIN30 ||
|
||||
ktype == KQuery::MIN60) {
|
||||
ktype == KQuery::MIN60 || ktype == KQuery::HOUR2) {
|
||||
filename = m_dirname + "\\" + market + "\\fzline\\" + market + code + ".lc5";
|
||||
} else if (ktype == KQuery::DAY || ktype == KQuery::WEEK || ktype == KQuery::MONTH ||
|
||||
ktype == KQuery::QUARTER || ktype == KQuery::HALFYEAR || ktype == KQuery::YEAR) {
|
||||
|
@ -69,7 +69,7 @@ Datetime::Datetime(unsigned long long datetime) {
|
||||
m_data = bt::ptime(d, bt::time_duration((unsigned short)hh, (unsigned short)mm, 0));
|
||||
} else {
|
||||
HKU_THROW_EXCEPTION(std::out_of_range,
|
||||
"Only suport YYYYMMDDhhmm or YYYYMMDD, but current param is {}",
|
||||
"Only support YYYYMMDDhhmm or YYYYMMDD, but current param is {}",
|
||||
datetime);
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +211,6 @@ void HKU_API startSpotAgent(bool print) {
|
||||
if (preloadParam.tryGet<bool>("min60", false)) {
|
||||
agent.addProcess(std::bind(updateStockMinData, std::placeholders::_1, KQuery::MIN60));
|
||||
}
|
||||
|
||||
if (preloadParam.tryGet<bool>("min3", false)) {
|
||||
agent.addProcess(std::bind(updateStockMinData, std::placeholders::_1, KQuery::MIN3));
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ void StrategyBase::_initDefaultParam() {
|
||||
setParam<bool>("enable_15min_clock", false);
|
||||
setParam<bool>("enable_30min_clock", false);
|
||||
setParam<bool>("enable_60min_clock", false);
|
||||
setParam<bool>("enable_2hour_clock", false);
|
||||
}
|
||||
|
||||
void StrategyBase::run() {
|
||||
@ -246,6 +247,7 @@ void StrategyBase::_addTimer() {
|
||||
_addClockEvent("enable_15min_clock", Minutes(15), openTime, closeTime);
|
||||
_addClockEvent("enable_30min_clock", Minutes(30), openTime, closeTime);
|
||||
_addClockEvent("enable_60min_clock", Minutes(60), openTime, closeTime);
|
||||
_addClockEvent("enable_2hour_clock", Hours(2), openTime, closeTime);
|
||||
}
|
||||
|
||||
void StrategyBase::_addClockEvent(const string& enable, TimeDelta delta, TimeDelta openTime,
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <boost/bind.hpp>
|
||||
#include <functional>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <algorithm>
|
||||
#include "TradeManager.h"
|
||||
@ -316,16 +316,16 @@ TradeRecordList TradeManager::getTradeList(const Datetime& start_date,
|
||||
|
||||
TradeRecord temp_record;
|
||||
temp_record.datetime = start_date;
|
||||
auto low =
|
||||
lower_bound(m_trade_list.begin(), m_trade_list.end(), temp_record,
|
||||
boost::bind(std::less<Datetime>(), boost::bind(&TradeRecord::datetime, _1),
|
||||
boost::bind(&TradeRecord::datetime, _2)));
|
||||
auto low = lower_bound(
|
||||
m_trade_list.begin(), m_trade_list.end(), temp_record,
|
||||
std::bind(std::less<Datetime>(), std::bind(&TradeRecord::datetime, std::placeholders::_1),
|
||||
std::bind(&TradeRecord::datetime, std::placeholders::_2)));
|
||||
|
||||
temp_record.datetime = end_date;
|
||||
auto high =
|
||||
lower_bound(m_trade_list.begin(), m_trade_list.end(), temp_record,
|
||||
boost::bind(std::less<Datetime>(), boost::bind(&TradeRecord::datetime, _1),
|
||||
boost::bind(&TradeRecord::datetime, _2)));
|
||||
auto high = lower_bound(
|
||||
m_trade_list.begin(), m_trade_list.end(), temp_record,
|
||||
std::bind(std::less<Datetime>(), std::bind(&TradeRecord::datetime, std::placeholders::_1),
|
||||
std::bind(&TradeRecord::datetime, std::placeholders::_2)));
|
||||
|
||||
result.insert(result.end(), low, high);
|
||||
|
||||
@ -863,11 +863,13 @@ TradeRecord TradeManager::buy(const Datetime& datetime, const Stock& stock, pric
|
||||
|
||||
if (result.datetime > m_broker_last_datetime) {
|
||||
list<OrderBrokerPtr>::const_iterator broker_iter = m_broker_list.begin();
|
||||
Datetime realtime, nulltime;
|
||||
for (; broker_iter != m_broker_list.end(); ++broker_iter) {
|
||||
Datetime realtime =
|
||||
realtime =
|
||||
(*broker_iter)->buy(datetime, stock.market(), stock.code(), realPrice, number);
|
||||
if (realtime != Null<Datetime>())
|
||||
if (realtime != nulltime && realtime > m_broker_last_datetime) {
|
||||
m_broker_last_datetime = realtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -951,10 +953,13 @@ TradeRecord TradeManager::sell(const Datetime& datetime, const Stock& stock, pri
|
||||
|
||||
if (result.datetime > m_broker_last_datetime) {
|
||||
list<OrderBrokerPtr>::const_iterator broker_iter = m_broker_list.begin();
|
||||
Datetime realtime, nulltime;
|
||||
for (; broker_iter != m_broker_list.end(); ++broker_iter) {
|
||||
Datetime realtime =
|
||||
realtime =
|
||||
(*broker_iter)->sell(datetime, stock.market(), stock.code(), realPrice, real_number);
|
||||
m_broker_last_datetime = realtime;
|
||||
if (realtime != nulltime && realtime > m_broker_last_datetime) {
|
||||
m_broker_last_datetime = realtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1527,9 +1532,10 @@ void TradeManager::updateWithWeight(const Datetime& datetime) {
|
||||
} /* for weight */
|
||||
} /* for position */
|
||||
|
||||
std::sort(new_trade_buffer.begin(), new_trade_buffer.end(),
|
||||
boost::bind(std::less<Datetime>(), boost::bind(&TradeRecord::datetime, _1),
|
||||
boost::bind(&TradeRecord::datetime, _2)));
|
||||
std::sort(
|
||||
new_trade_buffer.begin(), new_trade_buffer.end(),
|
||||
std::bind(std::less<Datetime>(), std::bind(&TradeRecord::datetime, std::placeholders::_1),
|
||||
std::bind(&TradeRecord::datetime, std::placeholders::_2)));
|
||||
|
||||
size_t total = new_trade_buffer.size();
|
||||
for (size_t i = 0; i < total; ++i) {
|
||||
|
@ -5,7 +5,6 @@
|
||||
* Author: fasiondog
|
||||
*/
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include "../../trade_manage/crt/crtTM.h"
|
||||
|
||||
#include "Portfolio.h"
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
* @param work_num 定时任务执行线程池线程数量
|
||||
*/
|
||||
TimerManager(size_t work_num = 1)
|
||||
: m_current_timer_id(-1), m_stop(true), m_work_num(work_num) {}
|
||||
: m_stop(true), m_current_timer_id(-1), m_work_num(work_num) {}
|
||||
|
||||
/** 析构函数 */
|
||||
~TimerManager() {
|
||||
|
@ -41,14 +41,15 @@ public:
|
||||
: m_done(false), m_worker_num(n), m_runnging_util_empty(util_empty) {
|
||||
try {
|
||||
// 先初始化相关资源,再启动线程
|
||||
for (int i = 0; i < m_worker_num; i++) {
|
||||
for (size_t i = 0; i < m_worker_num; i++) {
|
||||
// 创建工作线程及其任务队列
|
||||
m_threads_status.push_back(nullptr);
|
||||
m_queues.push_back(
|
||||
std::unique_ptr<MQStealQueue<task_type>>(new MQStealQueue<task_type>));
|
||||
}
|
||||
for (int i = 0; i < m_worker_num; i++) {
|
||||
m_threads.push_back(std::thread(&MQStealThreadPool::worker_thread, this, i));
|
||||
for (size_t i = 0; i < m_worker_num; i++) {
|
||||
m_threads.push_back(
|
||||
std::thread(&MQStealThreadPool::worker_thread, this, static_cast<int>(i)));
|
||||
}
|
||||
} catch (...) {
|
||||
m_done = true;
|
||||
|
@ -41,14 +41,15 @@ public:
|
||||
: m_done(false), m_worker_num(n), m_runnging_util_empty(util_empty) {
|
||||
try {
|
||||
// 先初始化相关资源,再启动线程
|
||||
for (int i = 0; i < m_worker_num; i++) {
|
||||
for (size_t i = 0; i < m_worker_num; i++) {
|
||||
// 创建工作线程及其任务队列
|
||||
m_threads_status.push_back(nullptr);
|
||||
m_queues.push_back(
|
||||
std::unique_ptr<ThreadSafeQueue<task_type>>(new ThreadSafeQueue<task_type>));
|
||||
}
|
||||
for (int i = 0; i < m_worker_num; i++) {
|
||||
m_threads.push_back(std::thread(&MQThreadPool::worker_thread, this, i));
|
||||
for (size_t i = 0; i < m_worker_num; i++) {
|
||||
m_threads.push_back(
|
||||
std::thread(&MQThreadPool::worker_thread, this, static_cast<int>(i)));
|
||||
}
|
||||
} catch (...) {
|
||||
m_done = true;
|
||||
|
@ -43,13 +43,14 @@ public:
|
||||
: m_done(false), m_runnging_util_empty(util_empty), m_worker_num(n) {
|
||||
try {
|
||||
// 先初始化相关资源,再启动线程
|
||||
for (int i = 0; i < m_worker_num; i++) {
|
||||
for (size_t i = 0; i < m_worker_num; i++) {
|
||||
// 创建工作线程及其任务队列
|
||||
m_threads_status.push_back(nullptr);
|
||||
m_queues.push_back(std::unique_ptr<WorkStealQueue>(new WorkStealQueue));
|
||||
}
|
||||
for (int i = 0; i < m_worker_num; i++) {
|
||||
m_threads.push_back(std::thread(&StealThreadPool::worker_thread, this, i));
|
||||
for (size_t i = 0; i < m_worker_num; i++) {
|
||||
m_threads.push_back(
|
||||
std::thread(&StealThreadPool::worker_thread, this, static_cast<int>(i)));
|
||||
}
|
||||
} catch (...) {
|
||||
m_done = true;
|
||||
@ -244,7 +245,7 @@ private:
|
||||
bool pop_task_from_other_thread_queue(task_type& task) {
|
||||
for (size_t i = 0; i < m_worker_num; ++i) {
|
||||
size_t index = (m_index + i + 1) % m_worker_num;
|
||||
if (index != m_index && m_queues[index]->try_steal(task)) {
|
||||
if (int(index) != m_index && m_queues[index]->try_steal(task)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -43,11 +43,12 @@ public:
|
||||
: m_done(false), m_worker_num(n), m_runnging_util_empty(util_empty) {
|
||||
try {
|
||||
// 先初始化相关资源,再启动线程
|
||||
for (int i = 0; i < m_worker_num; i++) {
|
||||
for (size_t i = 0; i < m_worker_num; i++) {
|
||||
m_threads_status.push_back(nullptr);
|
||||
}
|
||||
for (int i = 0; i < m_worker_num; i++) {
|
||||
m_threads.push_back(std::thread(&ThreadPool::worker_thread, this, i));
|
||||
for (size_t i = 0; i < m_worker_num; i++) {
|
||||
m_threads.push_back(
|
||||
std::thread(&ThreadPool::worker_thread, this, static_cast<int>(i)));
|
||||
}
|
||||
} catch (...) {
|
||||
m_done = true;
|
||||
|
@ -6,7 +6,7 @@ target("hikyuu")
|
||||
end
|
||||
|
||||
add_packages("fmt", "spdlog", "flatbuffers", "nng", "nlohmann_json", "cpp-httplib")
|
||||
if is_plat("windows") then
|
||||
if is_plat("windows", "linux") then
|
||||
add_packages("sqlite3")
|
||||
end
|
||||
|
||||
@ -39,17 +39,7 @@ target("hikyuu")
|
||||
end
|
||||
|
||||
if is_plat("linux") then
|
||||
add_packages("hdf5")
|
||||
if is_arch("x86_64") then
|
||||
if os.exists("/usr/lib64/mysql") then
|
||||
add_linkdirs("/usr/lib64/mysql")
|
||||
end
|
||||
if os.exists("/usr/lib/x86_64-linux-gnu") then
|
||||
add_linkdirs("/usr/lib/x86_64-linux-gnu")
|
||||
end
|
||||
end
|
||||
add_links("sqlite3")
|
||||
add_links("mysqlclient")
|
||||
add_packages("hdf5", "mysql")
|
||||
add_links("boost_date_time")
|
||||
add_links("boost_filesystem")
|
||||
add_links("boost_serialization")
|
||||
|
@ -32,13 +32,20 @@ typedef uint64_t u_int64_t;
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define explicit_bzero(s,n) memset(s, 0, n)
|
||||
#define explicit_bzero(s, n) memset(s, 0, n)
|
||||
#define DEF_WEAK(f)
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int bcrypt_hashpass(const char *key, const char *salt, char *encrypted, size_t encryptedlen);
|
||||
int encode_base64(char *, const u_int8_t *, size_t);
|
||||
int timingsafe_bcmp(const void *b1, const void *b2, size_t n);
|
||||
int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, uint8_t *key, size_t keylen, unsigned int rounds);
|
||||
int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen,
|
||||
uint8_t *key, size_t keylen, unsigned int rounds);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -26,12 +26,7 @@ target("hkuserver")
|
||||
end
|
||||
|
||||
if is_plat("linux") then
|
||||
if is_arch("x86_64") then
|
||||
if os.exists("/usr/lib64/mysql") then
|
||||
add_linkdirs("/usr/lib64/mysql")
|
||||
end
|
||||
add_linkdirs("/usr/lib/x86_64-linux-gnu")
|
||||
end
|
||||
add_packages("mysql")
|
||||
end
|
||||
|
||||
if is_plat("macosx") then
|
||||
|
@ -12,7 +12,7 @@ package("hdf5")
|
||||
elseif is_plat("linux") then
|
||||
add_urls("https://github.com/fasiondog/hikyuu/releases/download/1.1.9/hdf5-$(version)-linux-x64.zip",
|
||||
"https://gitee.com/fasiondog/hikyuu/releases/download/1.1.9/hdf5-$(version)-linux-x64.zip")
|
||||
add_versions("1.12.2", "8a6b571168481fba273e1f0c7838d417f38222b5d93250388d2ddff5ff7f2611")
|
||||
add_versions("1.12.2", "e0f4357ea7bfa0132c3edba9b517635736191f920ce7a3aeef5e89dbe5b2dd27")
|
||||
end
|
||||
|
||||
on_load("windows", "linux", function (package)
|
||||
|
@ -7,6 +7,7 @@ package("hdf5_D")
|
||||
if is_plat("windows") then
|
||||
add_urls("https://github.com/fasiondog/hikyuu/releases/download/1.1.9/hdf5_D-$(version)-win-x64.zip",
|
||||
"https://gitee.com/fasiondog/hikyuu/releases/download/1.1.9/hdf5_D-$(version)-win-x64.zip")
|
||||
add_versions("1.12.2", "6ea3ab5a4b0bb0f48eaef28cfe747ac5c072c06519a4888c1a59cfaf75399049")
|
||||
add_versions("1.10.4", "5b1bd27e054f885bf9cac0beffcacbe180e251c5d8c12c0652a96055f2784b46")
|
||||
end
|
||||
|
||||
|
@ -7,11 +7,17 @@ package("mysql")
|
||||
add_urls("https://github.com/fasiondog/hikyuu/releases/download/1.1.9/mysql-$(version)-win-x64.zip",
|
||||
"https://gitee.com/fasiondog/hikyuu/attach_files/935339/download/mysql-$(version)-win-x64.zip")
|
||||
add_versions("8.0.21", "de21694aa230a00b52b28babbce9bb150d990ba1f539edf8d193586dce3844ae")
|
||||
elseif is_plat("linux") then
|
||||
add_urls("https://github.com/fasiondog/hikyuu/releases/download/1.1.9/mysql-$(version)-linux-x86_64.zip",
|
||||
"https://gitee.com/fasiondog/hikyuu/releases/download/1.1.9/mysql-$(version)-linux-x86_64.zip")
|
||||
add_versions("8.0.31", "1775a94f4a59cfb03593e6e70891de33a0cc8713573afdfc9ca0482415a8ecd3")
|
||||
end
|
||||
|
||||
on_install("windows", function (package)
|
||||
on_install("windows", "linux", function (package)
|
||||
os.cp("include", package:installdir())
|
||||
os.cp("lib", package:installdir())
|
||||
os.cp("bin", package:installdir())
|
||||
if package:is_plat("windows") then
|
||||
os.cp("bin", package:installdir())
|
||||
end
|
||||
end)
|
||||
|
||||
|
@ -17,8 +17,8 @@ struct Constant {
|
||||
: null_datetime(Null<Datetime>()),
|
||||
inf(std::numeric_limits<double>::infinity()),
|
||||
nan(std::numeric_limits<double>::quiet_NaN()),
|
||||
max_double(std::numeric_limits<double>::max()),
|
||||
null_double(Null<double>()),
|
||||
max_double(std::numeric_limits<double>::max()),
|
||||
null_price(Null<price_t>()),
|
||||
null_int(Null<int>()),
|
||||
null_size(Null<size_t>()),
|
||||
|
@ -132,7 +132,14 @@ inline void Parameter::set<object>(const string& name, const object& o) {
|
||||
extract<int> x2(o);
|
||||
if (x2.check()) {
|
||||
int overflow;
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
long val = PyLong_AsLongAndOverflow(o.ptr(), &overflow);
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
if (overflow == 0) {
|
||||
m_params[name] = x2();
|
||||
} else {
|
||||
|
3
setup.py
3
setup.py
@ -123,7 +123,8 @@ def build_boost(mode):
|
||||
# ' --with-serialization'.format(mode))
|
||||
os.chdir(current_dir)
|
||||
else:
|
||||
cmd = 'cd {boost} ; if [ ! -f "b2" ]; then ./bootstrap.sh ; fi; '\
|
||||
# 新版的 boost 配置 project-cofig.jam 中的 python 版本无效,必须在当前 python 下重新编译 b2
|
||||
cmd = 'cd {boost} ; ./bootstrap.sh; '\
|
||||
'./b2 {mode} link=shared address-model=64 -j 4 --with-python --with-serialization; '\
|
||||
'./b2 {mode} link=static address-model=64 cxxflags=-fPIC -j 4 --with-date_time '\
|
||||
'--with-filesystem --with-system --with-test --with-atomic; '\
|
||||
|
@ -23,6 +23,7 @@ min5 = False
|
||||
min15 = False
|
||||
min30 = False
|
||||
min60 = False
|
||||
hour2 = False
|
||||
day_max = 100000
|
||||
week_max = 100000
|
||||
month_max = 100000
|
||||
@ -34,7 +35,7 @@ min5_max = 5120
|
||||
min15_max = 5120
|
||||
min30_max = 5120
|
||||
min60_max = 5120
|
||||
|
||||
hour2_max = 5120
|
||||
|
||||
[baseinfo]
|
||||
type = sqlite3
|
||||
|
@ -23,6 +23,7 @@ min5 = False
|
||||
min15 = False
|
||||
min30 = False
|
||||
min60 = False
|
||||
hour2 = False
|
||||
day_max = 100000
|
||||
week_max = 100000
|
||||
month_max = 100000
|
||||
@ -34,6 +35,7 @@ min5_max = 5120
|
||||
min15_max = 5120
|
||||
min30_max = 5120
|
||||
min60_max = 5120
|
||||
hour2_max = 5120
|
||||
|
||||
[baseinfo]
|
||||
type = sqlite3
|
||||
|
30
xmake.lua
30
xmake.lua
@ -9,7 +9,7 @@ if not is_plat("windows") then
|
||||
end
|
||||
|
||||
-- version
|
||||
set_version("1.2.5", {build="%Y%m%d%H%M"})
|
||||
set_version("1.2.7", {build="%Y%m%d%H%M"})
|
||||
set_configvar("LOG_ACTIVE_LEVEL", 0) -- 激活的日志级别
|
||||
--if is_mode("debug") then
|
||||
-- set_configvar("LOG_ACTIVE_LEVEL", 0) -- 激活的日志级别
|
||||
@ -40,7 +40,10 @@ end
|
||||
set_languages("cxx17", "C99")
|
||||
|
||||
local hdf5_version = "1.12.2"
|
||||
local mysql_version = "8.0.21"
|
||||
local mysql_version = "8.0.31"
|
||||
if is_plat("windows") then
|
||||
mysql_version = "8.0.21"
|
||||
end
|
||||
|
||||
add_repositories("project-repo hikyuu_extern_libs")
|
||||
if is_plat("windows") then
|
||||
@ -52,26 +55,22 @@ if is_plat("windows") then
|
||||
end
|
||||
add_requires("mysql " .. mysql_version)
|
||||
elseif is_plat("linux") then
|
||||
add_requires("hdf5 " .. hdf5_version)
|
||||
add_requires("hdf5 " .. hdf5_version, {system = false})
|
||||
add_requires("mysql " .. mysql_version, {system = false})
|
||||
elseif is_plat("macosx") then
|
||||
add_requires("brew::hdf5")
|
||||
end
|
||||
|
||||
-- add_requires("fmt 8.1.1", {system=false, configs = {header_only = true}})
|
||||
add_requires("spdlog", {system=false, configs = {header_only = true, fmt_external=true, vs_runtime = "MD"}})
|
||||
add_requireconfs("spdlog.fmt", {override = true, version = "8.1.1", configs = {header_only = true}})
|
||||
add_requires("sqlite3", {system=false, configs = {shared=true, vs_runtime="MD", cxflags="-fPIC"}})
|
||||
add_requires("flatbuffers", {system=false, configs = {vs_runtime="MD"}})
|
||||
add_requires("nng", {system=false, configs = {vs_runtime="MD", cxflags="-fPIC"}})
|
||||
add_requires("nlohmann_json", {system=false})
|
||||
add_requires("cpp-httplib", {system=false})
|
||||
add_requires("zlib", {system=false})
|
||||
|
||||
if is_plat("linux") and linuxos.name() == "ubuntu" then
|
||||
add_requires("apt::libmysqlclient-dev", "apt::libsqlite3-dev")
|
||||
elseif is_plat("macosx") then
|
||||
add_requires("brew::hdf5")
|
||||
else
|
||||
add_requires("sqlite3", {configs = {shared=true, vs_runtime="MD", cxflags="-fPIC"}})
|
||||
end
|
||||
|
||||
add_defines("SPDLOG_DISABLE_DEFAULT_LOGGER") -- 禁用 spdlog 默认 logger
|
||||
|
||||
set_objectdir("$(buildir)/$(mode)/$(plat)/$(arch)/.objs")
|
||||
@ -84,15 +83,6 @@ add_linkdirs("$(env BOOST_LIB)")
|
||||
--add_defines("BOOST_ALL_DYN_LINK")
|
||||
add_defines("BOOST_SERIALIZATION_DYN_LINK")
|
||||
|
||||
if is_host("linux") then
|
||||
if is_arch("x86_64") then
|
||||
add_linkdirs("/usr/lib64")
|
||||
if os.exists("/usr/lib/x86_64-linux-gnu") then
|
||||
add_linkdirs("/usr/lib/x86_64-linux-gnu")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- is release now
|
||||
if is_mode("release") then
|
||||
if is_plat("windows") then
|
||||
|
Loading…
Reference in New Issue
Block a user