[bug fix]
This commit is contained in:
parent
5580336f4b
commit
b94065902a
14
README.md
14
README.md
@ -83,6 +83,20 @@
|
|||||||
- 支持bar方式回测/组合回测
|
- 支持bar方式回测/组合回测
|
||||||
- 增强期货交易模板
|
- 增强期货交易模板
|
||||||
|
|
||||||
|
13、 增加App: cta_stock, 包括:
|
||||||
|
|
||||||
|
- 增加baostock数据源,可下载股票基本信息,复权因子,非复权5Min数据k线,满足大部分Cta策略的回测了。
|
||||||
|
- 使用tdx的历史逐笔成交数据,可缓存每日数据=>pkb2文件,支持tick回测。
|
||||||
|
- 独立的CTA引擎 cta_stock,运行股票CTA策略时,替代原版cta_strategy引擎
|
||||||
|
- 提供股票专用模板,支持目标股票买入卖出,市场盘面算法交易,支持策略多股票持久化
|
||||||
|
- 支持策略中获取账号资金/可用余额/当前仓位/风控仓位
|
||||||
|
- 支持策略中获取账号所有股票持仓
|
||||||
|
- 支持bar/tick方式回测/组合回测
|
||||||
|
- 支持可转债日内交易回测,支持动态前复权。
|
||||||
|
- 支持盘前复权信息事件【待更新】
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
大佳
|
大佳
|
||||||
QQ/Wechat:28888502
|
QQ/Wechat:28888502
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ class AccountRecorder(BaseEngine):
|
|||||||
def update_order(self, event: Event):
|
def update_order(self, event: Event):
|
||||||
"""更新当日记录"""
|
"""更新当日记录"""
|
||||||
order = event.data
|
order = event.data
|
||||||
self.write_log(u'记录委托日志:{}'.format(order.__dict__))
|
# self.write_log(u'记录委托日志:{}'.format(order.__dict__))
|
||||||
if len(order.sys_orderid) == 0:
|
if len(order.sys_orderid) == 0:
|
||||||
# 未有系统的委托编号,不做持久化
|
# 未有系统的委托编号,不做持久化
|
||||||
return
|
return
|
||||||
@ -441,7 +441,7 @@ class AccountRecorder(BaseEngine):
|
|||||||
def update_strategy_snapshot(self, event: Event):
|
def update_strategy_snapshot(self, event: Event):
|
||||||
"""更新策略切片"""
|
"""更新策略切片"""
|
||||||
snapshot = event.data
|
snapshot = event.data
|
||||||
self.write_log(f"保存切片,{snapshot.get('account_id')},策略:{snapshot.get('strategy')}")
|
# self.write_log(f"保存切片,{snapshot.get('account_id')},策略:{snapshot.get('strategy')}")
|
||||||
klines = snapshot.pop('klines', None)
|
klines = snapshot.pop('klines', None)
|
||||||
if klines:
|
if klines:
|
||||||
self.write_log(f"转换 =>BSON.binary.Binary")
|
self.write_log(f"转换 =>BSON.binary.Binary")
|
||||||
|
@ -5,7 +5,7 @@ Defines constants and objects used in CtaCrypto App.
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from vnpy.trader.constant import Direction, Offset, Interval
|
from vnpy.trader.constant import Direction, Offset, Interval, Exchange
|
||||||
|
|
||||||
APP_NAME = "CtaStock"
|
APP_NAME = "CtaStock"
|
||||||
STOPORDER_PREFIX = "STOP"
|
STOPORDER_PREFIX = "STOP"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
数字货币CTA策略运行引擎
|
股票CTA策略运行引擎
|
||||||
华富资产:
|
华富资产:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ class CtaEngine(BaseEngine):
|
|||||||
self.load_strategy_class()
|
self.load_strategy_class()
|
||||||
self.load_strategy_setting()
|
self.load_strategy_setting()
|
||||||
|
|
||||||
self.write_log("CTA策略数字货币引擎初始化成功")
|
self.write_log("CTA策略股票引擎初始化成功")
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""停止所属有的策略"""
|
"""停止所属有的策略"""
|
||||||
@ -218,6 +218,7 @@ class CtaEngine(BaseEngine):
|
|||||||
# 主动获取所有策略得持仓信息
|
# 主动获取所有策略得持仓信息
|
||||||
all_strategy_pos = self.get_all_strategy_pos()
|
all_strategy_pos = self.get_all_strategy_pos()
|
||||||
|
|
||||||
|
if dt.minute % 5 == 0:
|
||||||
# 比对仓位,使用上述获取得持仓信息,不用重复获取
|
# 比对仓位,使用上述获取得持仓信息,不用重复获取
|
||||||
self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
|
self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
|
||||||
|
|
||||||
@ -1456,7 +1457,7 @@ class CtaEngine(BaseEngine):
|
|||||||
d.update(strategy.get_parameters())
|
d.update(strategy.get_parameters())
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def compare_pos(self):
|
def compare_pos(self,strategy_pos_list=[]):
|
||||||
"""
|
"""
|
||||||
对比账号&策略的持仓,不同的话则发出微信提醒
|
对比账号&策略的持仓,不同的话则发出微信提醒
|
||||||
:return:
|
:return:
|
||||||
@ -1468,6 +1469,7 @@ class CtaEngine(BaseEngine):
|
|||||||
self.write_log(u'开始对比账号&策略的持仓')
|
self.write_log(u'开始对比账号&策略的持仓')
|
||||||
|
|
||||||
# 获取当前策略得持仓
|
# 获取当前策略得持仓
|
||||||
|
if len(strategy_pos_list) == 0:
|
||||||
strategy_pos_list = self.get_all_strategy_pos()
|
strategy_pos_list = self.get_all_strategy_pos()
|
||||||
self.write_log(u'策略持仓清单:{}'.format(strategy_pos_list))
|
self.write_log(u'策略持仓清单:{}'.format(strategy_pos_list))
|
||||||
|
|
||||||
@ -1520,12 +1522,11 @@ class CtaEngine(BaseEngine):
|
|||||||
compare_info = ''
|
compare_info = ''
|
||||||
for vt_symbol in sorted(vt_symbols):
|
for vt_symbol in sorted(vt_symbols):
|
||||||
# 发送不一致得结果
|
# 发送不一致得结果
|
||||||
symbol_pos = compare_pos.pop(vt_symbol)
|
symbol_pos = compare_pos.pop(vt_symbol, {
|
||||||
d_long = {
|
'账号多单': 0,
|
||||||
'account_id': self.engine_config.get('account_id', '-'),
|
'策略多单': 0,
|
||||||
'vt_symbol': vt_symbol,
|
'多单策略': []
|
||||||
'direction': Direction.LONG.value,
|
})
|
||||||
'strategy_list': symbol_pos.get('多单策略', [])}
|
|
||||||
|
|
||||||
# 多单都一致
|
# 多单都一致
|
||||||
if round(symbol_pos['账号多单'], 7) == round(symbol_pos['策略多单'], 7):
|
if round(symbol_pos['账号多单'], 7) == round(symbol_pos['策略多单'], 7):
|
||||||
@ -1596,7 +1597,7 @@ class CtaEngine(BaseEngine):
|
|||||||
self.add_strategy(
|
self.add_strategy(
|
||||||
class_name=strategy_config["class_name"],
|
class_name=strategy_config["class_name"],
|
||||||
strategy_name=strategy_name,
|
strategy_name=strategy_name,
|
||||||
vt_symbol=strategy_config["vt_symbol"],
|
vt_symbols=strategy_config["vt_symbols"],
|
||||||
setting=strategy_config["setting"],
|
setting=strategy_config["setting"],
|
||||||
auto_init=strategy_config.get('auto_init', False),
|
auto_init=strategy_config.get('auto_init', False),
|
||||||
auto_start=strategy_config.get('auto_start', False)
|
auto_start=strategy_config.get('auto_start', False)
|
||||||
@ -1612,7 +1613,7 @@ class CtaEngine(BaseEngine):
|
|||||||
old_config = self.strategy_setting.get('strategy_name', {})
|
old_config = self.strategy_setting.get('strategy_name', {})
|
||||||
new_config = {
|
new_config = {
|
||||||
"class_name": strategy.__class__.__name__,
|
"class_name": strategy.__class__.__name__,
|
||||||
"vt_symbol": strategy.vt_symbol,
|
"vt_symbols": strategy.vt_symbols,
|
||||||
"auto_init": auto_init,
|
"auto_init": auto_init,
|
||||||
"auto_start": auto_start,
|
"auto_start": auto_start,
|
||||||
"setting": setting
|
"setting": setting
|
||||||
@ -1631,7 +1632,7 @@ class CtaEngine(BaseEngine):
|
|||||||
"""
|
"""
|
||||||
if strategy_name not in self.strategy_setting:
|
if strategy_name not in self.strategy_setting:
|
||||||
return
|
return
|
||||||
self.write_log(f'移除CTA数字货币引擎{strategy_name}的配置')
|
self.write_log(f'移除CTA股票引擎{strategy_name}的配置')
|
||||||
self.strategy_setting.pop(strategy_name)
|
self.strategy_setting.pop(strategy_name)
|
||||||
save_json(self.setting_filename, self.strategy_setting)
|
save_json(self.setting_filename, self.strategy_setting)
|
||||||
|
|
||||||
@ -1698,7 +1699,7 @@ class CtaEngine(BaseEngine):
|
|||||||
if strategy:
|
if strategy:
|
||||||
subject = f"{strategy.strategy_name}"
|
subject = f"{strategy.strategy_name}"
|
||||||
else:
|
else:
|
||||||
subject = "CTA策略数字货币引擎"
|
subject = "CTA策略股票引擎"
|
||||||
|
|
||||||
self.main_engine.send_email(subject, msg)
|
self.main_engine.send_email(subject, msg)
|
||||||
|
|
||||||
@ -1712,6 +1713,6 @@ class CtaEngine(BaseEngine):
|
|||||||
if strategy:
|
if strategy:
|
||||||
subject = f"{strategy.strategy_name}"
|
subject = f"{strategy.strategy_name}"
|
||||||
else:
|
else:
|
||||||
subject = "CTACRYPTO引擎"
|
subject = "CTASTOCK引擎"
|
||||||
|
|
||||||
send_wx_msg(content=f'{subject}:{msg}')
|
send_wx_msg(content=f'{subject}:{msg}')
|
||||||
|
@ -142,7 +142,7 @@ class CtaManager(QtWidgets.QWidget):
|
|||||||
|
|
||||||
if n == editor.Accepted:
|
if n == editor.Accepted:
|
||||||
setting = editor.get_setting()
|
setting = editor.get_setting()
|
||||||
vt_symbol = setting.pop("vt_symbol")
|
vt_symbols = setting.pop("vt_symbols").split(",")
|
||||||
strategy_name = setting.pop("strategy_name")
|
strategy_name = setting.pop("strategy_name")
|
||||||
auto_init = setting.pop("auto_init", False)
|
auto_init = setting.pop("auto_init", False)
|
||||||
auto_start = setting.pop("auto_start", False)
|
auto_start = setting.pop("auto_start", False)
|
||||||
@ -206,12 +206,12 @@ class StrategyManager(QtWidgets.QFrame):
|
|||||||
save_button.clicked.connect(self.save_strategy)
|
save_button.clicked.connect(self.save_strategy)
|
||||||
|
|
||||||
strategy_name = self._data["strategy_name"]
|
strategy_name = self._data["strategy_name"]
|
||||||
vt_symbol = self._data["vt_symbol"]
|
#vt_symbol = self._data["vt_symbol"]
|
||||||
class_name = self._data["class_name"]
|
class_name = self._data["class_name"]
|
||||||
author = self._data["author"]
|
author = self._data["author"]
|
||||||
|
|
||||||
label_text = (
|
label_text = (
|
||||||
f"{strategy_name} - {vt_symbol} ({class_name} by {author})"
|
f"{strategy_name} - ({class_name} by {author})"
|
||||||
)
|
)
|
||||||
label = QtWidgets.QLabel(label_text)
|
label = QtWidgets.QLabel(label_text)
|
||||||
label.setAlignment(QtCore.Qt.AlignCenter)
|
label.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
@ -411,7 +411,7 @@ class SettingEditor(QtWidgets.QDialog):
|
|||||||
if self.class_name:
|
if self.class_name:
|
||||||
self.setWindowTitle(f"添加策略:{self.class_name}")
|
self.setWindowTitle(f"添加策略:{self.class_name}")
|
||||||
button_text = "添加"
|
button_text = "添加"
|
||||||
parameters = {"strategy_name": "", "vt_symbol": "", "auto_init": True, "auto_start": True}
|
parameters = {"strategy_name": "", "vt_symbols": "", "auto_init": True, "auto_start": True}
|
||||||
parameters.update(self.parameters)
|
parameters.update(self.parameters)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -1158,9 +1158,13 @@ class BackTestingEngine(object):
|
|||||||
# 3. 则在实际中的成交价会是100而不是105,因为委托发出时市场的最优价格是100
|
# 3. 则在实际中的成交价会是100而不是105,因为委托发出时市场的最优价格是100
|
||||||
if buy_cross:
|
if buy_cross:
|
||||||
trade_price = min(order.price, buy_best_cross_price)
|
trade_price = min(order.price, buy_best_cross_price)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
trade_price = max(order.price, sell_best_cross_price)
|
trade_price = max(order.price, sell_best_cross_price)
|
||||||
|
|
||||||
|
# renko bar较为特殊,使用委托价进行成交
|
||||||
|
if trade.vt_symbol.startswith('future_renko'):
|
||||||
|
trade_price = order.price
|
||||||
|
|
||||||
trade.price = trade_price
|
trade.price = trade_price
|
||||||
|
|
||||||
# 记录该合约来自哪个策略实例
|
# 记录该合约来自哪个策略实例
|
||||||
|
@ -85,10 +85,31 @@ class PortfolioTestingEngine(BackTestingEngine):
|
|||||||
"date": str,
|
"date": str,
|
||||||
"time": str
|
"time": str
|
||||||
}
|
}
|
||||||
|
if vt_symbol.startswith('future_renko'):
|
||||||
|
data_types.update({
|
||||||
|
"color": str,
|
||||||
|
"seconds": int,
|
||||||
|
"high_seconds": int,
|
||||||
|
"low_seconds": int,
|
||||||
|
"height": float,
|
||||||
|
"up_band": float,
|
||||||
|
"down_band": float,
|
||||||
|
"low_time": str,
|
||||||
|
"high_time": str
|
||||||
|
})
|
||||||
# 加载csv文件 =》 dateframe
|
# 加载csv文件 =》 dateframe
|
||||||
symbol_df = pd.read_csv(bar_file, dtype=data_types)
|
symbol_df = pd.read_csv(bar_file, dtype=data_types)
|
||||||
|
if len(symbol_df)==0:
|
||||||
|
self.write_error(f'回测时加载{vt_symbol} csv文件{bar_file}失败。')
|
||||||
|
return False
|
||||||
|
|
||||||
|
first_dt = symbol_df.iloc[0]['datetime']
|
||||||
|
if '.' in first_dt:
|
||||||
|
datetime_format = "%Y-%m-%d %H:%M:%S.%f"
|
||||||
|
else:
|
||||||
|
datetime_format = "%Y-%m-%d %H:%M:%S"
|
||||||
# 转换时间,str =》 datetime
|
# 转换时间,str =》 datetime
|
||||||
symbol_df["datetime"] = pd.to_datetime(symbol_df["datetime"], format="%Y-%m-%d %H:%M:%S")
|
symbol_df["datetime"] = pd.to_datetime(symbol_df["datetime"], format=datetime_format)
|
||||||
# 设置时间为索引
|
# 设置时间为索引
|
||||||
symbol_df = symbol_df.set_index("datetime")
|
symbol_df = symbol_df.set_index("datetime")
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import sys
|
|||||||
import traceback
|
import traceback
|
||||||
import talib as ta
|
import talib as ta
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
@ -49,6 +50,14 @@ def get_cta_bar_type(bar_name: str):
|
|||||||
return CtaDayBar, 1
|
return CtaDayBar, 1
|
||||||
else:
|
else:
|
||||||
return CtaDayBar, int(interval)
|
return CtaDayBar, int(interval)
|
||||||
|
|
||||||
|
if bar_name.startswith('W'):
|
||||||
|
interval = bar_name.replace('W', '')
|
||||||
|
if len(interval) == 0:
|
||||||
|
return CtaWeekBar, 1
|
||||||
|
else:
|
||||||
|
return CtaWeekBar, int(interval)
|
||||||
|
|
||||||
raise Exception(u'{}参数错误'.format(bar_name))
|
raise Exception(u'{}参数错误'.format(bar_name))
|
||||||
|
|
||||||
|
|
||||||
@ -298,6 +307,9 @@ class CtaLineBar(object):
|
|||||||
self.paramList.append('para_bias2_len')
|
self.paramList.append('para_bias2_len')
|
||||||
self.paramList.append('para_bias3_len')
|
self.paramList.append('para_bias3_len')
|
||||||
|
|
||||||
|
self.paramList.append('para_skdj_n')
|
||||||
|
self.paramList.append('para_skdj_m')
|
||||||
|
|
||||||
self.paramList.append('para_bd_len')
|
self.paramList.append('para_bd_len')
|
||||||
|
|
||||||
self.paramList.append('is_7x24')
|
self.paramList.append('is_7x24')
|
||||||
@ -403,6 +415,9 @@ class CtaLineBar(object):
|
|||||||
self.para_yb_ref = 1 # 趋势线参照周期
|
self.para_yb_ref = 1 # 趋势线参照周期
|
||||||
self.para_yb_len = 10 # 趋势线观测周期
|
self.para_yb_len = 10 # 趋势线观测周期
|
||||||
|
|
||||||
|
self.para_skdj_m = 0 # 3 # SKDJ NN
|
||||||
|
self.para_skdj_n = 0 # 9 # SKDJ MM
|
||||||
|
|
||||||
self.para_golden_n = 0 # 黄金分割的观测周期(一般设置为60,或120)
|
self.para_golden_n = 0 # 黄金分割的观测周期(一般设置为60,或120)
|
||||||
|
|
||||||
self.para_active_area = False # 是否激活区域划分
|
self.para_active_area = False # 是否激活区域划分
|
||||||
@ -494,12 +509,12 @@ class CtaLineBar(object):
|
|||||||
self.line_upper_atan = []
|
self.line_upper_atan = []
|
||||||
self.line_middle_atan = []
|
self.line_middle_atan = []
|
||||||
self.line_lower_atan = []
|
self.line_lower_atan = []
|
||||||
self._rt_upper = 0
|
self._rt_upper = None
|
||||||
self._rt_middle = 0
|
self._rt_middle = None
|
||||||
self._rt_lower = 0
|
self._rt_lower = None
|
||||||
self._rt_upper_atan = 0
|
self._rt_upper_atan = None
|
||||||
self._rt_middle_atan = 0
|
self._rt_middle_atan = None
|
||||||
self._rt_lower_atan = 0
|
self._rt_lower_atan = None
|
||||||
|
|
||||||
self.cur_upper = 0 # 最后一根K的Boll上轨数值(与MinDiff取整)
|
self.cur_upper = 0 # 最后一根K的Boll上轨数值(与MinDiff取整)
|
||||||
self.cur_middle = 0 # 最后一根K的Boll中轨数值(与MinDiff取整)
|
self.cur_middle = 0 # 最后一根K的Boll中轨数值(与MinDiff取整)
|
||||||
@ -560,13 +575,19 @@ class CtaLineBar(object):
|
|||||||
|
|
||||||
# K 线的CCI计算数据
|
# K 线的CCI计算数据
|
||||||
self.line_cci = []
|
self.line_cci = []
|
||||||
|
self.line_cci_ema = []
|
||||||
self.cur_cci = None
|
self.cur_cci = None
|
||||||
|
self.cur_cci_ema = None
|
||||||
self._rt_cci = None
|
self._rt_cci = None
|
||||||
|
self._rt_cci_ema = None
|
||||||
|
|
||||||
# 卡尔曼过滤器
|
# 卡尔曼过滤器
|
||||||
self.kf = None
|
self.kf = None
|
||||||
self.line_state_mean = [] # 卡尔曼均线
|
self.line_state_mean = [] # 卡尔曼均线
|
||||||
|
self.line_state_upper = [] # 卡尔曼均线+2标准差
|
||||||
|
self.line_state_lower = [] # 卡尔曼均线-2标准差
|
||||||
self.line_state_covar = [] # 方差
|
self.line_state_covar = [] # 方差
|
||||||
|
self.cur_state_std = None
|
||||||
|
|
||||||
# SAR 抛物线
|
# SAR 抛物线
|
||||||
self.cur_sar_direction = '' # up/down
|
self.cur_sar_direction = '' # up/down
|
||||||
@ -639,6 +660,12 @@ class CtaLineBar(object):
|
|||||||
self._bd_fast = 0
|
self._bd_fast = 0
|
||||||
self._bd_slow = 0
|
self._bd_slow = 0
|
||||||
|
|
||||||
|
# SKDJ
|
||||||
|
self.line_skdj_k = []
|
||||||
|
self.line_skdj_d = []
|
||||||
|
self.cur_skdj_k = 0
|
||||||
|
self.cur_skdj_d = 0
|
||||||
|
|
||||||
def set_params(self, setting: dict = {}):
|
def set_params(self, setting: dict = {}):
|
||||||
"""设置参数"""
|
"""设置参数"""
|
||||||
d = self.__dict__
|
d = self.__dict__
|
||||||
@ -816,6 +843,7 @@ class CtaLineBar(object):
|
|||||||
self.__count_area(bar)
|
self.__count_area(bar)
|
||||||
self.__count_bias()
|
self.__count_bias()
|
||||||
self.__count_bd()
|
self.__count_bd()
|
||||||
|
self.__count_skdj()
|
||||||
self.export_to_csv(bar)
|
self.export_to_csv(bar)
|
||||||
|
|
||||||
self.rt_executed = False
|
self.rt_executed = False
|
||||||
@ -968,8 +996,8 @@ class CtaLineBar(object):
|
|||||||
round(self.line_d[-1], self.round_n),
|
round(self.line_d[-1], self.round_n),
|
||||||
round(self.line_j[-1], self.round_n))
|
round(self.line_j[-1], self.round_n))
|
||||||
|
|
||||||
if self.para_cci_len > 0 and len(self.line_cci) > 0:
|
if self.para_cci_len > 0 and len(self.line_cci) > 0 and len(self.line_cci_ema) > 0:
|
||||||
msg = msg + u',Cci({0}):{1}'.format(self.para_cci_len, self.line_cci[-1])
|
msg = msg + u',Cci({0}):{1}, EMA(Cci):{2}'.format(self.para_cci_len, self.line_cci[-1], self.line_cci_ema[-1])
|
||||||
|
|
||||||
if (self.para_boll_len > 0 or self.para_boll_tb_len > 0) and len(self.line_boll_upper) > 0:
|
if (self.para_boll_len > 0 or self.para_boll_tb_len > 0) and len(self.line_boll_upper) > 0:
|
||||||
msg = msg + u',Boll({}):std:{},mid:{},up:{},low:{},Atan:[mid:{},up:{},low:{}]'. \
|
msg = msg + u',Boll({}):std:{},mid:{},up:{},low:{},Atan:[mid:{},up:{},low:{}]'. \
|
||||||
@ -1246,6 +1274,33 @@ class CtaLineBar(object):
|
|||||||
del self.line_pre_low[0]
|
del self.line_pre_low[0]
|
||||||
self.line_pre_low.append(preLow)
|
self.line_pre_low.append(preLow)
|
||||||
|
|
||||||
|
def get_sar(self, direction, cur_sar, cur_af=0, sar_limit=0.2, sar_step=0.02):
|
||||||
|
"""
|
||||||
|
抛物线计算方法
|
||||||
|
:param direction: Direction
|
||||||
|
:param cur_sar: 当前抛物线价格
|
||||||
|
:param cur_af: 当前抛物线价格
|
||||||
|
:param sar_limit: 最大加速范围
|
||||||
|
:param sar_step: 加速因子
|
||||||
|
:return: 新的
|
||||||
|
"""
|
||||||
|
if np.isnan(self.high_array[-1]):
|
||||||
|
return cur_sar, cur_af
|
||||||
|
# 向上抛物线
|
||||||
|
if direction == Direction.LONG:
|
||||||
|
af = min(sar_limit, cur_af + sar_step)
|
||||||
|
ep = self.high_array[-1]
|
||||||
|
sar = cur_sar + af * (ep - cur_sar)
|
||||||
|
return sar, af
|
||||||
|
# 向下抛物线
|
||||||
|
elif direction == Direction.SHORT:
|
||||||
|
af = min(sar_limit, cur_af + sar_step)
|
||||||
|
ep = self.low_array[-1]
|
||||||
|
sar = cur_sar + af * (ep - cur_sar)
|
||||||
|
return sar, af
|
||||||
|
else:
|
||||||
|
return cur_sar, cur_af
|
||||||
|
|
||||||
def __count_sar(self):
|
def __count_sar(self):
|
||||||
"""计算K线的SAR"""
|
"""计算K线的SAR"""
|
||||||
|
|
||||||
@ -1280,19 +1335,28 @@ class CtaLineBar(object):
|
|||||||
self.cur_sar_count = 0
|
self.cur_sar_count = 0
|
||||||
self.line_sar_top.append(self.line_bar[-2].high_price) # SAR的谷顶
|
self.line_sar_top.append(self.line_bar[-2].high_price) # SAR的谷顶
|
||||||
self.line_sar_buttom.append(self.line_bar[-2].low_price) # SAR的波底
|
self.line_sar_buttom.append(self.line_bar[-2].low_price) # SAR的波底
|
||||||
|
|
||||||
|
# 当前处于上升抛物线
|
||||||
elif len(self.line_sar_sr_up) > 0:
|
elif len(self.line_sar_sr_up) > 0:
|
||||||
|
|
||||||
|
# # K线low,仍然在上升抛物线上方,延续
|
||||||
if self.low_array[-1] > self.line_sar_sr_up[-1]:
|
if self.low_array[-1] > self.line_sar_sr_up[-1]:
|
||||||
|
|
||||||
sr0 = self.line_sar_sr_up[-1]
|
sr0 = self.line_sar_sr_up[-1]
|
||||||
ep0 = self.high_array[-1] # 文华使用前一个K线的最高价
|
ep0 = self.high_array[-1] # 文华使用前一个K线的最高价
|
||||||
af0 = min(self.para_sar_limit,
|
af0 = min(self.para_sar_limit,
|
||||||
self.line_sar_af_up[-1] + self.para_sar_step) # 文华的af随着K线的数目增加而递增,没有判断新高
|
self.line_sar_af_up[-1] + self.para_sar_step) # 文华的af随着K线的数目增加而递增,没有判断新高
|
||||||
|
# 计算出新的抛物线价格
|
||||||
sr = sr0 + af0 * (ep0 - sr0)
|
sr = sr0 + af0 * (ep0 - sr0)
|
||||||
|
|
||||||
self.line_sar_sr_up.append(sr)
|
self.line_sar_sr_up.append(sr)
|
||||||
self.line_sar_ep_up.append(ep0)
|
self.line_sar_ep_up.append(ep0)
|
||||||
self.line_sar_af_up.append(af0)
|
self.line_sar_af_up.append(af0)
|
||||||
self.line_sar.append(sr)
|
self.line_sar.append(sr)
|
||||||
self.cur_sar_count += 1
|
self.cur_sar_count += 1
|
||||||
# self.write_log('Up: sr0={},ep0={},af0={},sr={}'.format(sr0, ep0, af0, sr))
|
# self.write_log('Up: sr0={},ep0={},af0={},sr={}'.format(sr0, ep0, af0, sr))
|
||||||
|
|
||||||
|
# K线最低,触碰上升的抛物线 =》 转为 下降抛物线
|
||||||
elif self.low_array[-1] <= self.line_sar_sr_up[-1]:
|
elif self.low_array[-1] <= self.line_sar_sr_up[-1]:
|
||||||
ep0 = max(self.high_array[-len(self.line_sar_sr_up):])
|
ep0 = max(self.high_array[-len(self.line_sar_sr_up):])
|
||||||
sr0 = ep0
|
sr0 = ep0
|
||||||
@ -2982,17 +3046,46 @@ class CtaLineBar(object):
|
|||||||
format(len(self.line_bar), self.para_cci_len + 2))
|
format(len(self.line_bar), self.para_cci_len + 2))
|
||||||
return
|
return
|
||||||
|
|
||||||
# 计算第1根RSI曲线
|
# HIGH = self.high_array[self.high_array > 0]
|
||||||
|
# LOW = self.low_array[self.low_array > 0]
|
||||||
|
# CLOSE = self.close_array[self.close_array > 0]
|
||||||
|
# min_length = min([len(HIGH), len(LOW), len(CLOSE)])
|
||||||
|
# if min_length < (self.para_cci_len + 10):
|
||||||
|
# return
|
||||||
|
# HIGH = HIGH[-min_length:]
|
||||||
|
# LOW = LOW[-min_length:]
|
||||||
|
# CLOSE = CLOSE[-min_length:]
|
||||||
|
# TP = (HIGH + LOW + CLOSE) / 3
|
||||||
|
|
||||||
cur_cci = ta.CCI(high=self.high_array[-2 * self.para_cci_len:], low=self.low_array[-2 * self.para_cci_len:],
|
TP = self.mid3_array[-self.para_cci_len:]
|
||||||
close=self.close_array[-2 * self.para_cci_len:], timeperiod=self.para_cci_len)[-1]
|
# MA = pd.Series(data=TP).rolling(window=self.para_cci_len).mean().values
|
||||||
|
# MD = pd.Series(data=(TP - MA)).abs().rolling(window=self.para_cci_len).mean().values
|
||||||
|
# CCI = (TP - MA) / (0.015 * MD)
|
||||||
|
MA = np.mean(TP)
|
||||||
|
MD = np.mean(np.abs(TP - MA))
|
||||||
|
CCI = (TP[-1] - MA) / (0.015 * MD)
|
||||||
|
|
||||||
self.cur_cci = round(float(cur_cci), self.round_n)
|
self.cur_cci = round(CCI, self.round_n)
|
||||||
|
|
||||||
|
# cur_cci = ta.CCI(high=self.high_array[-2 * self.para_cci_len:], low=self.low_array[-2 * self.para_cci_len:],
|
||||||
|
# close=self.close_array[-2 * self.para_cci_len:], timeperiod=self.para_cci_len)[-1]
|
||||||
|
|
||||||
|
# self.cur_cci = round(float(cur_cci), self.round_n)
|
||||||
|
|
||||||
if len(self.line_cci) > self.max_hold_bars:
|
if len(self.line_cci) > self.max_hold_bars:
|
||||||
del self.line_cci[0]
|
del self.line_cci[0]
|
||||||
self.line_cci.append(self.cur_cci)
|
self.line_cci.append(self.cur_cci)
|
||||||
|
|
||||||
|
if len(self.line_cci) < 30:
|
||||||
|
self.cur_cci_ema = self.cur_cci
|
||||||
|
else:
|
||||||
|
self.cur_cci_ema = self.__ema(self.__ema(self.__ema(self.line_cci[-30:], 3), 2), 2)[-1]
|
||||||
|
|
||||||
|
if len(self.line_cci_ema) > self.max_hold_bars:
|
||||||
|
del self.line_cci_ema[0]
|
||||||
|
self.line_cci_ema.append(self.cur_cci_ema)
|
||||||
|
|
||||||
|
|
||||||
def rt_count_cci(self):
|
def rt_count_cci(self):
|
||||||
"""实时计算CCI值"""
|
"""实时计算CCI值"""
|
||||||
if self.para_cci_len <= 0:
|
if self.para_cci_len <= 0:
|
||||||
@ -3004,11 +3097,19 @@ class CtaLineBar(object):
|
|||||||
format(len(self.line_bar), self.para_cci_len + 2))
|
format(len(self.line_bar), self.para_cci_len + 2))
|
||||||
return
|
return
|
||||||
|
|
||||||
self._rt_cci = ta.CCI(high=np.append(self.high_array[-2 * self.para_cci_len:], [self.line_bar[-1].high_price]),
|
HIGH = np.append(self.high_array[-2 * self.para_cci_len:], [self.line_bar[-1].high_price])
|
||||||
low=np.append(self.low_array[-2 * self.para_cci_len:], [self.line_bar[-1].low_price]),
|
LOW = np.append(self.low_array[-2 * self.para_cci_len:], [self.line_bar[-1].low_price])
|
||||||
close=np.append(self.close_array[-2 * self.para_cci_len:],
|
CLOSE = np.append(self.close_array[-2 * self.para_cci_len:],[self.line_bar[-1].close_price])
|
||||||
[self.line_bar[-1].close_price]),
|
TP = (HIGH + LOW + CLOSE) / 3
|
||||||
timeperiod=self.para_cci_len)[-1]
|
TP = TP[-self.para_cci_len:]
|
||||||
|
MA = np.mean(TP)
|
||||||
|
MD = np.mean(np.abs(TP - MA))
|
||||||
|
CCI = (TP[-1] - MA) / (0.015 * MD)
|
||||||
|
|
||||||
|
self._rt_cci = CCI
|
||||||
|
rt_line_cci = np.append(self.line_cci[-30:], [CCI])
|
||||||
|
self._rt_cci_ema = self.__ema(self.__ema(self.__ema(rt_line_cci, 3), 2), 2)[-1]
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rt_cci(self):
|
def rt_cci(self):
|
||||||
@ -3021,7 +3122,7 @@ class CtaLineBar(object):
|
|||||||
"""计算卡尔曼过滤器均线"""
|
"""计算卡尔曼过滤器均线"""
|
||||||
if not self.para_active_kf or self.kf is None:
|
if not self.para_active_kf or self.kf is None:
|
||||||
return
|
return
|
||||||
if self.bar_len < 2:
|
if self.bar_len < 26:
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(self.line_state_mean) == 0 or len(self.line_state_covar) == 0:
|
if len(self.line_state_mean) == 0 or len(self.line_state_covar) == 0:
|
||||||
@ -3035,9 +3136,10 @@ class CtaLineBar(object):
|
|||||||
self.write_log(u'导入卡尔曼过滤器失败,需先安装 pip install pykalman')
|
self.write_log(u'导入卡尔曼过滤器失败,需先安装 pip install pykalman')
|
||||||
self.para_active_kf = False
|
self.para_active_kf = False
|
||||||
|
|
||||||
state_means, state_covariances = self.kf.filter(self.close_array)
|
state_means, state_covariances = self.kf.filter(self.close_array[-1])
|
||||||
m = state_means[-1].item()
|
m = state_means[-1].item()
|
||||||
c = state_covariances[-1].item()
|
c = state_covariances[-1].item()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
m = self.line_state_mean[-1]
|
m = self.line_state_mean[-1]
|
||||||
c = self.line_state_covar[-1]
|
c = self.line_state_covar[-1]
|
||||||
@ -3047,13 +3149,22 @@ class CtaLineBar(object):
|
|||||||
observation=self.close_array[-1])
|
observation=self.close_array[-1])
|
||||||
m = state_means[-1].item()
|
m = state_means[-1].item()
|
||||||
c = state_covariances[-1].item()
|
c = state_covariances[-1].item()
|
||||||
|
std_len = 26 if self.bar_len > 26 else self.bar_len
|
||||||
|
std = np.std(self.close_array[-std_len:], ddof=1)
|
||||||
|
self.cur_state_std = std
|
||||||
if len(self.line_state_mean) > self.max_hold_bars:
|
if len(self.line_state_mean) > self.max_hold_bars:
|
||||||
del self.line_state_mean[0]
|
del self.line_state_mean[0]
|
||||||
if len(self.line_state_covar) > self.max_hold_bars:
|
if len(self.line_state_covar) > self.max_hold_bars:
|
||||||
del self.line_state_covar[0]
|
del self.line_state_covar[0]
|
||||||
|
|
||||||
|
if len(self.line_state_upper) > self.max_hold_bars:
|
||||||
|
del self.line_state_upper[0]
|
||||||
|
if len(self.line_state_lower) > self.max_hold_bars:
|
||||||
|
del self.line_state_lower[0]
|
||||||
|
|
||||||
|
self.line_state_upper.append(m + 3 * std)
|
||||||
self.line_state_mean.append(m)
|
self.line_state_mean.append(m)
|
||||||
|
self.line_state_lower.append(m - 3 * std)
|
||||||
self.line_state_covar.append(c)
|
self.line_state_covar.append(c)
|
||||||
|
|
||||||
def __count_period(self, bar):
|
def __count_period(self, bar):
|
||||||
@ -4025,6 +4136,15 @@ class CtaLineBar(object):
|
|||||||
return self.line_bias3[-1]
|
return self.line_bias3[-1]
|
||||||
return self._rt_bias3
|
return self._rt_bias3
|
||||||
|
|
||||||
|
def __ema(self, data, span):
|
||||||
|
return pd.Series(data=data).ewm(span=span, adjust=False).mean().values
|
||||||
|
|
||||||
|
def __iema(self, this_value, prev_value, span):
|
||||||
|
return (2 * prev_value + (span - 1) * this_value) / (span + 1)
|
||||||
|
|
||||||
|
def __std(self, data, span):
|
||||||
|
return pd.Series(data=data).rolling(window=span).std().values
|
||||||
|
|
||||||
def __count_bd(self):
|
def __count_bd(self):
|
||||||
"""计算波段快/慢线"""
|
"""计算波段快/慢线"""
|
||||||
#
|
#
|
||||||
@ -4032,18 +4152,25 @@ class CtaLineBar(object):
|
|||||||
# 不计算
|
# 不计算
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(self.line_bar) < 2 * self.para_bd_len:
|
# 修改 By Huang Jianwei
|
||||||
|
var2 = self.mid4_array
|
||||||
|
var2 = var2[var2 > 0]
|
||||||
|
if len(var2) < (5 * self.para_bd_len):
|
||||||
return
|
return
|
||||||
|
var3 = self.__ema(var2, self.para_bd_len)
|
||||||
|
var4 = self.__std(var2, self.para_bd_len)
|
||||||
|
|
||||||
mid4_ema_array = ta.EMA(self.mid4_array, self.para_bd_len)
|
## 检查是否有不合理的std
|
||||||
|
var4_mask = var4 < 1e-5 # 找出不合理的std
|
||||||
|
var4[var4_mask] = 1e-5 # 用一个小的正数替换
|
||||||
|
var5 = ((var2 - var3) / var4 * 100 + 200) / 4 # 计算var5
|
||||||
|
var5[var4_mask] = 0 # 把不合理的std计算的结果抹掉,用0填充
|
||||||
|
# 因为var2-var3是一种类似乖离率的东西,长期均值是接近0的,所以用0填充有合理性
|
||||||
|
|
||||||
mid4_std = np.std(self.mid4_array[-self.para_bd_len:], ddof=1)
|
var6 = (self.__ema(var5, 5) - 25) * 1.56
|
||||||
|
fast_array = self.__ema(var6, 2) * 1.22
|
||||||
mid4_ema_diff_array = self.mid4_array - mid4_ema_array
|
slow_array = self.__ema(fast_array, 2)
|
||||||
var5_array = (mid4_ema_diff_array / mid4_std * 100 + 200) / 4
|
# 修改完毕
|
||||||
var6_array = (ta.EMA(var5_array, 5) - 25) * 1.56
|
|
||||||
fast_array = ta.EMA(var6_array, 2) * 1.22
|
|
||||||
slow_array = ta.EMA(fast_array, 2)
|
|
||||||
|
|
||||||
# 快线/慢线最后记录,追加到line_bd_fast/ list_bd_slow中
|
# 快线/慢线最后记录,追加到line_bd_fast/ list_bd_slow中
|
||||||
if len(self.line_bd_fast) > self.max_hold_bars:
|
if len(self.line_bd_fast) > self.max_hold_bars:
|
||||||
@ -4069,27 +4196,29 @@ class CtaLineBar(object):
|
|||||||
# 不计算
|
# 不计算
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(self.line_bar) < 2 * self.para_bd_len:
|
var2 = self.close_array[self.close_array>0]
|
||||||
|
if len(var2) < (5 * self.para_bd_len):
|
||||||
return
|
return
|
||||||
bar_mid4 = (self.line_bar[-1].close_price * 2 + self.line_bar[-1].high_price + self.line_bar[-1].low_price)/4
|
bar_mid4 = (self.line_bar[-1].close_price * 2 + self.line_bar[-1].high_price + self.line_bar[-1].low_price)/4
|
||||||
bar_mid4 = round(bar_mid4, self.round_n)
|
bar_mid4 = round(bar_mid4, self.round_n)
|
||||||
|
|
||||||
mid4_array = np.append(self.mid4_array, [bar_mid4])
|
mid4_array = np.append(self.mid4_array, [bar_mid4])
|
||||||
mid4_ema_array = ta.EMA(mid4_array, self.para_bd_len)
|
mid4_ema_array = self.__ema(mid4_array, self.para_bd_len)
|
||||||
|
|
||||||
mid4_std = np.std(mid4_array[-self.para_bd_len:], ddof=1)
|
mid4_std = self.__std(mid4_array, self.para_bd_len)
|
||||||
|
|
||||||
mid4_ema_diff_array = mid4_array - mid4_ema_array
|
mid4_ema_diff_array = mid4_array - mid4_ema_array
|
||||||
var5_array = (mid4_ema_diff_array / mid4_std * 100 + 200) / 4
|
var5_array = (mid4_ema_diff_array / mid4_std * 100 + 200) / 4
|
||||||
var6_array = (ta.EMA(var5_array, 5) - 25) * 1.56
|
var6_array = (self.__ema(var5_array, 5) - 25) * 1.56
|
||||||
fast_array = ta.EMA(var6_array, 2) * 1.22
|
fast_array = self.__ema(var6_array, 2) * 1.22
|
||||||
slow_array = ta.EMA(fast_array, 2)
|
slow_array = self.__ema(fast_array, 2)
|
||||||
|
|
||||||
self._bd_fast = fast_array[-1]
|
self._bd_fast = fast_array[-1]
|
||||||
self._bd_slow = slow_array[-1]
|
self._bd_slow = slow_array[-1]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rt_bd_fast(self):
|
def rt_bd_fast(self):
|
||||||
|
"""波段快线(实时值)"""
|
||||||
self.check_rt_funcs(self.rt_count_bd)
|
self.check_rt_funcs(self.rt_count_bd)
|
||||||
if self._bd_fast is None and len(self.para_bd_len) > 0:
|
if self._bd_fast is None and len(self.para_bd_len) > 0:
|
||||||
return self.line_bd_fast[-1]
|
return self.line_bd_fast[-1]
|
||||||
@ -4097,12 +4226,46 @@ class CtaLineBar(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def rt_bd_slow(self):
|
def rt_bd_slow(self):
|
||||||
|
"""波段慢线(实时值)"""
|
||||||
self.check_rt_funcs(self.rt_count_bd)
|
self.check_rt_funcs(self.rt_count_bd)
|
||||||
if self._bd_slow is None and len(self.para_bd_len) > 0:
|
if self._bd_slow is None and len(self.para_bd_len) > 0:
|
||||||
return self.line_bd_slow[-1]
|
return self.line_bd_slow[-1]
|
||||||
return self._bd_slow
|
return self._bd_slow
|
||||||
|
|
||||||
|
|
||||||
|
def __count_skdj(self):
|
||||||
|
"""计算波段快/慢线"""
|
||||||
|
#
|
||||||
|
if self.para_skdj_m <= 0 or self.para_skdj_n <= 0:
|
||||||
|
# 不计算
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(self.line_bar) < 5 * min(self.para_skdj_m, self.para_skdj_n):
|
||||||
|
return
|
||||||
|
|
||||||
|
NN = self.para_skdj_n
|
||||||
|
MM = self.para_skdj_m
|
||||||
|
|
||||||
|
LOWV = pd.Series(data=self.low_array).rolling(window=NN).min().values
|
||||||
|
HIGHV = pd.Series(data=self.high_array).rolling(window=NN).max().values
|
||||||
|
CLOSE = self.close_array
|
||||||
|
RSV = self.__ema((CLOSE-LOWV)/(HIGHV-LOWV)*100, MM)
|
||||||
|
K = self.__ema(RSV, MM)
|
||||||
|
D = pd.Series(data=K).rolling(window=MM).mean().values
|
||||||
|
|
||||||
|
|
||||||
|
if len(self.line_skdj_k) > self.max_hold_bars:
|
||||||
|
self.line_skdj_k.pop(0)
|
||||||
|
if not np.isnan(K[-1]):
|
||||||
|
self.line_skdj_k.append(K[-1])
|
||||||
|
self.cur_skdj_k = K[-1]
|
||||||
|
|
||||||
|
if len(self.line_skdj_d) > self.max_hold_bars:
|
||||||
|
self.line_skdj_d.pop(0)
|
||||||
|
if not np.isnan(D[-1]):
|
||||||
|
self.line_skdj_d.append(D[-1])
|
||||||
|
self.cur_skdj_d = D[-1]
|
||||||
|
|
||||||
def write_log(self, content):
|
def write_log(self, content):
|
||||||
"""记录CTA日志"""
|
"""记录CTA日志"""
|
||||||
self.strategy.write_log(u'[' + self.name + u']' + content)
|
self.strategy.write_log(u'[' + self.name + u']' + content)
|
||||||
|
@ -75,7 +75,6 @@ class TdxStockData(object):
|
|||||||
|
|
||||||
self.strategy = strategy
|
self.strategy = strategy
|
||||||
self.best_ip = None
|
self.best_ip = None
|
||||||
self.symbol_exchange_dict = {} # tdx合约与vn交易所的字典
|
|
||||||
self.symbol_market_dict = {} # tdx合约与tdx市场的字典
|
self.symbol_market_dict = {} # tdx合约与tdx市场的字典
|
||||||
|
|
||||||
self.config = get_cache_config(TDX_STOCK_CONFIG)
|
self.config = get_cache_config(TDX_STOCK_CONFIG)
|
||||||
@ -211,12 +210,10 @@ class TdxStockData(object):
|
|||||||
tdx_code, market_str = symbol.split('.')
|
tdx_code, market_str = symbol.split('.')
|
||||||
# 1, 上交所 , 0, 深交所
|
# 1, 上交所 , 0, 深交所
|
||||||
market_id = 1 if market_str.upper() in ['XSHG', Exchange.SSE.value] else 0
|
market_id = 1 if market_str.upper() in ['XSHG', Exchange.SSE.value] else 0
|
||||||
self.symbol_exchange_dict.update({tdx_code: symbol}) # tdx合约与vn交易所的字典
|
|
||||||
self.symbol_market_dict.update({tdx_code: market_id}) # tdx合约与tdx市场的字典
|
self.symbol_market_dict.update({tdx_code: market_id}) # tdx合约与tdx市场的字典
|
||||||
else:
|
else:
|
||||||
market_id = get_tdx_market_code(symbol)
|
market_id = get_tdx_market_code(symbol)
|
||||||
tdx_code = symbol
|
tdx_code = symbol
|
||||||
self.symbol_exchange_dict.update({symbol: symbol}) # tdx合约与vn交易所的字典
|
|
||||||
self.symbol_market_dict.update({symbol: market_id}) # tdx合约与tdx市场的字典
|
self.symbol_market_dict.update({symbol: market_id}) # tdx合约与tdx市场的字典
|
||||||
name = self.get_name(tdx_code, market_id)
|
name = self.get_name(tdx_code, market_id)
|
||||||
|
|
||||||
@ -416,12 +413,10 @@ class TdxStockData(object):
|
|||||||
if '.' in symbol:
|
if '.' in symbol:
|
||||||
tdx_code, market_str = symbol.split('.')
|
tdx_code, market_str = symbol.split('.')
|
||||||
market_code = 1 if market_str.upper() in ['XSHG', Exchange.SSE.value] else 0
|
market_code = 1 if market_str.upper() in ['XSHG', Exchange.SSE.value] else 0
|
||||||
self.symbol_exchange_dict.update({tdx_code: symbol}) # tdx合约与vn交易所的字典
|
|
||||||
self.symbol_market_dict.update({tdx_code: market_code}) # tdx合约与tdx市场的字典
|
self.symbol_market_dict.update({tdx_code: market_code}) # tdx合约与tdx市场的字典
|
||||||
else:
|
else:
|
||||||
market_code = get_tdx_market_code(symbol)
|
market_code = get_tdx_market_code(symbol)
|
||||||
tdx_code = symbol
|
tdx_code = symbol
|
||||||
self.symbol_exchange_dict.update({symbol: symbol}) # tdx合约与vn交易所的字典
|
|
||||||
self.symbol_market_dict.update({symbol: market_code}) # tdx合约与tdx市场的字典
|
self.symbol_market_dict.update({symbol: market_code}) # tdx合约与tdx市场的字典
|
||||||
|
|
||||||
symbol_config = self.symbol_dict.get(f'{tdx_code}_{market_code}', {})
|
symbol_config = self.symbol_dict.get(f'{tdx_code}_{market_code}', {})
|
||||||
|
@ -562,8 +562,8 @@ class BinancefRestApi(RestClient):
|
|||||||
gateway_name=self.gateway_name,
|
gateway_name=self.gateway_name,
|
||||||
)
|
)
|
||||||
self.gateway.on_position(position)
|
self.gateway.on_position(position)
|
||||||
if position.symbol == 'BTCUSDT':
|
#if position.symbol == 'BTCUSDT':
|
||||||
self.gateway.write_log(f'{position.__dict__}\n {d}')
|
# self.gateway.write_log(f'{position.__dict__}\n {d}')
|
||||||
# self.gateway.write_log("持仓信息查询成功")
|
# self.gateway.write_log("持仓信息查询成功")
|
||||||
|
|
||||||
def on_query_order(self, data: dict, request: Request) -> None:
|
def on_query_order(self, data: dict, request: Request) -> None:
|
||||||
|
@ -33,6 +33,8 @@ SETTINGS: Dict[str, Any] = {
|
|||||||
"database.user": "root",
|
"database.user": "root",
|
||||||
"database.password": "",
|
"database.password": "",
|
||||||
"database.authentication_source": "admin", # for mongodb
|
"database.authentication_source": "admin", # for mongodb
|
||||||
|
|
||||||
|
"huafu.data_source": "" # 华富资产自建数据源
|
||||||
}
|
}
|
||||||
|
|
||||||
# Load global setting from json file.
|
# Load global setting from json file.
|
||||||
|
Loading…
Reference in New Issue
Block a user