[一般更新] Flask8检查代码,套利模板,股票下载更新,天勤更新
This commit is contained in:
parent
74d156b3ae
commit
b32ca3b9d5
@ -20,7 +20,7 @@ import baostock as bs
|
||||
from vnpy.trader.constant import Exchange
|
||||
from vnpy.data.tdx.tdx_common import get_tdx_market_code
|
||||
from vnpy.trader.utility import load_json, get_csv_last_dt, extract_vt_symbol
|
||||
from vnpy.data.stock.stock_base import get_stock_base
|
||||
from vnpy.data.stock.stock_base import update_stock_base, get_stock_base
|
||||
# 保存的1分钟指数 bar目录
|
||||
bar_data_folder = os.path.abspath(os.path.join(vnpy_root, 'bar_data'))
|
||||
|
||||
@ -34,6 +34,9 @@ if __name__ == "__main__":
|
||||
if login_msg.error_code != '0':
|
||||
print(f'证券宝登录错误代码:{login_msg.error_code}, 错误信息:{login_msg.error_msg}')
|
||||
|
||||
print('更新股票基本信息')
|
||||
update_stock_base()
|
||||
|
||||
symbol_dict = get_stock_base()
|
||||
if len(sys.argv) >= 2 and sys.argv[1].lower() == 'all':
|
||||
stock_list = list(symbol_dict.keys())
|
||||
@ -43,7 +46,6 @@ if __name__ == "__main__":
|
||||
stock_list = load_json('stock_list.json')
|
||||
print('读取本地stock_list.json文件,共{}个'.format(len(stock_list)))
|
||||
|
||||
|
||||
day_fields = "date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,isST"
|
||||
min_fields = "date,time,code,open,high,low,close,volume,amount,adjustflag"
|
||||
|
||||
@ -74,7 +76,10 @@ if __name__ == "__main__":
|
||||
exchange_name = '深交所'
|
||||
exchange_code = 'sz'
|
||||
|
||||
symbol_info = symbol_dict.get(vt_symbol)
|
||||
symbol_info = symbol_dict.get(vt_symbol,None)
|
||||
if symbol_info is None:
|
||||
print(f'找不到{vt_symbol}得配置信息', file=sys.stderr)
|
||||
continue
|
||||
if symbol_info['类型'] == '指数':
|
||||
continue
|
||||
stock_name = symbol_info.get('name')
|
||||
|
@ -1,4 +1,4 @@
|
||||
six==1.13.0
|
||||
six
|
||||
PyQt5
|
||||
pyqtgraph
|
||||
dataclasses; python_version<="3.6"
|
||||
@ -8,7 +8,7 @@ websocket-client
|
||||
peewee
|
||||
mongoengine
|
||||
numpy
|
||||
pandas==0.25.2
|
||||
pandas
|
||||
matplotlib
|
||||
seaborn
|
||||
futu-api
|
||||
|
@ -1945,7 +1945,7 @@ class BackTestingEngine(object):
|
||||
self.daily_max_drawdown_rate = drawdown_rate
|
||||
self.max_drawdown_rate_time = data['date']
|
||||
|
||||
msg = u'{}: net={}, capital={} max={} margin={} commission={}, pos: {}' \
|
||||
msg = u'{}: net={}, capital={} max={} holding_profit={} commission={}, pos: {}' \
|
||||
.format(data['date'],
|
||||
data['net'], c, m,
|
||||
today_holding_profit,
|
||||
|
@ -11,6 +11,7 @@ import sys
|
||||
import os
|
||||
import gc
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import traceback
|
||||
import random
|
||||
import bz2
|
||||
@ -425,7 +426,10 @@ class PortfolioTestingEngine(BackTestingEngine):
|
||||
last_price=tick_data['price'],
|
||||
volume=tick_data['volume']
|
||||
)
|
||||
|
||||
if not isinstance(tick.last_price,float):
|
||||
continue
|
||||
if np.isnan(tick.last_price):
|
||||
continue
|
||||
self.new_tick(tick)
|
||||
|
||||
# 结束一个交易日后,更新每日净值
|
||||
|
@ -11,6 +11,7 @@ import sys
|
||||
import os
|
||||
import gc
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import traceback
|
||||
|
||||
import bz2
|
||||
@ -426,6 +427,9 @@ class SpreadTestingEngine(BackTestingEngine):
|
||||
bid_volume_1=int(tick_data['bid_volume_1'])
|
||||
)
|
||||
|
||||
if np.isnan(tick.ask_price_1) or np.isnan(tick.bid_price_1):
|
||||
continue
|
||||
|
||||
self.new_tick(tick)
|
||||
|
||||
# 结束一个交易日后,更新每日净值
|
||||
|
@ -63,6 +63,12 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
self.klines = {} # K线组件字典: kline_name: kline
|
||||
|
||||
self.cur_datetime = None # 当前Tick时间
|
||||
self.cur_mi_tick = None # 最新的主力合约tick( vt_symbol)
|
||||
self.cur_99_tick = None # 最新得指数合约tick( idx_symbol)
|
||||
|
||||
self.cur_mi_price = None # 当前价(主力合约 vt_symbol)
|
||||
self.cur_99_price = None # 当前价(tick时,根据tick更新,onBar回测时,根据bar.close更新)
|
||||
|
||||
self.cur_act_tick = None # 最新的主动腿合约tick( act_vt_symbol)
|
||||
self.cur_pas_tick = None # 最新得被动腿合约tick( pas_vt_symbol)
|
||||
self.cur_spd_tick = None # 价差tick
|
||||
@ -124,7 +130,6 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
self.write_log(u'保存k线缓存数据')
|
||||
self.save_klines_to_cache()
|
||||
|
||||
|
||||
def save_klines_to_cache(self, kline_names: list = []):
|
||||
"""
|
||||
保存K线数据到缓存
|
||||
@ -748,8 +753,8 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
grid.order_ids.remove(order.vt_orderid)
|
||||
|
||||
# 网格的所有委托单已经执行完毕
|
||||
if len(grid.order_ids) == 0:
|
||||
grid.order_status = False
|
||||
#if len(grid.order_ids) == 0:
|
||||
# grid.order_status = False
|
||||
|
||||
self.gt.save()
|
||||
self.write_log(u'网格信息更新:{}'.format(grid.__dict__))
|
||||
@ -776,7 +781,7 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
self.write_log(f'{order_vt_symbol}涨停,不做buy')
|
||||
return
|
||||
|
||||
# 发送委托
|
||||
# FAK发送委托追单
|
||||
vt_orderids = self.buy(price=buy_price,
|
||||
volume=order_volume,
|
||||
vt_symbol=order_vt_symbol,
|
||||
@ -855,8 +860,8 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
self.write_log(f'移除grid中order_ids:{order.vt_orderid}')
|
||||
grid.order_ids.remove(order.vt_orderid)
|
||||
|
||||
if not grid.order_ids:
|
||||
grid.order_status = False
|
||||
#if not grid.order_ids:
|
||||
# grid.order_status = False
|
||||
|
||||
self.gt.save()
|
||||
self.active_orders.update({order.vt_orderid: old_order})
|
||||
@ -872,7 +877,7 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
return
|
||||
|
||||
if not self.trading:
|
||||
self.write_error(u'当前不允许交易')
|
||||
self.write_error(f'{self.cur_datetime} 当前不允许交易')
|
||||
return
|
||||
|
||||
# 直接更新“未完成委托单”,更新volume,Retry次数
|
||||
@ -906,8 +911,8 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
if order.vt_orderid in grid.order_ids:
|
||||
self.write_log(f'移除grid中order_ids:{order.vt_orderid}')
|
||||
grid.order_ids.remove(order.vt_orderid)
|
||||
if not grid.order_ids:
|
||||
grid.order_status = False
|
||||
#if not grid.order_ids:
|
||||
# grid.order_status = False
|
||||
self.gt.save()
|
||||
self.write_log(u'更新网格=>{}'.format(grid.__dict__))
|
||||
|
||||
@ -1001,8 +1006,8 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
if order.vt_orderid in grid.order_ids:
|
||||
self.write_log(f'移除grid中order_ids:{order.vt_orderid}')
|
||||
grid.order_ids.remove(order.vt_orderid)
|
||||
if len(grid.order_ids) == 0:
|
||||
grid.order_status = False
|
||||
#if len(grid.order_ids) == 0:
|
||||
# grid.order_status = False
|
||||
self.gt.save()
|
||||
self.active_orders.update({order.vt_orderid: old_order})
|
||||
|
||||
@ -1047,15 +1052,17 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
self.active_orders.update({vt_orderid: order_info})
|
||||
ret = self.cancel_order(str(vt_orderid))
|
||||
if not ret:
|
||||
self.write_log(u'撤单失败,更新状态为撤单成功')
|
||||
self.write_log(f'{vt_orderid}撤单失败,更新状态为撤单成功')
|
||||
order_info.update({'status': Status.CANCELLED})
|
||||
self.active_orders.update({vt_orderid: order_info})
|
||||
else:
|
||||
self.write_log(f'{vt_orderid}撤单成功')
|
||||
if order_grid:
|
||||
if vt_orderid in order_grid.order_ids:
|
||||
self.write_log(f'{vt_orderid}存在网格委托队列{order_grid.order_ids}中,移除')
|
||||
order_grid.order_ids.remove(vt_orderid)
|
||||
if len(order_grid.order_ids) == 0:
|
||||
order_grid.order_status = False
|
||||
#if len(order_grid.order_ids) == 0:
|
||||
# order_grid.order_status = False
|
||||
continue
|
||||
|
||||
# 处理状态为‘撤销’的委托单
|
||||
@ -1234,10 +1241,10 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
self.write_log(u'停止状态,不开仓')
|
||||
return []
|
||||
if not self.allow_trading_open:
|
||||
self.write_log(u'不允许开仓')
|
||||
self.write_log(f'{self.cur_datetime}不允许开仓')
|
||||
return []
|
||||
if self.force_trading_close:
|
||||
self.write_log(u'强制平仓日,不开仓')
|
||||
self.write_log(f'{self.cur_datetime}强制平仓日,不开仓')
|
||||
return []
|
||||
# 检查流动性缺失
|
||||
if not self.check_liquidity( direction=Direction.SHORT,
|
||||
@ -1266,7 +1273,7 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
f'委托价:{self.cur_act_tick.bid_price_1}')
|
||||
return []
|
||||
|
||||
# 开多被动腿
|
||||
# 开多被动腿(FAK或者限价单)
|
||||
pas_vt_orderids = self.buy(vt_symbol=self.pas_vt_symbol,
|
||||
lock=self.pas_exchange==Exchange.CFFEX,
|
||||
price=self.cur_pas_tick.ask_price_1,
|
||||
@ -1303,10 +1310,10 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
self.write_log(u'停止状态,不开仓')
|
||||
return []
|
||||
if not self.allow_trading_open:
|
||||
self.write_log(u'不允许开仓')
|
||||
self.write_log(f'{self.cur_datetime}不允许开仓')
|
||||
return []
|
||||
if self.force_trading_close:
|
||||
self.write_log(u'强制平仓日,不开仓')
|
||||
self.write_log(f'{self.cur_datetime}强制平仓日,不开仓')
|
||||
return []
|
||||
# 检查流动性缺失
|
||||
if not self.check_liquidity(
|
||||
@ -1324,7 +1331,7 @@ class CtaSpreadTemplate(CtaTemplate):
|
||||
self.write_log(u'价差{}不满足:{}'.format(self.cur_spd_tick.bid_price_1, grid.open_price))
|
||||
return []
|
||||
|
||||
# 开多主动腿
|
||||
# 开多主动腿(FAK 或者限价单)
|
||||
act_vt_orderids = self.buy(vt_symbol=self.act_vt_symbol,
|
||||
lock=self.act_exchange==Exchange.CFFEX,
|
||||
price=self.cur_act_tick.ask_price_1,
|
||||
|
@ -300,6 +300,7 @@ class StrategyManager(QtWidgets.QFrame):
|
||||
tns_csv = os.path.abspath(os.path.join(self.cta_engine.get_data_path(), f'{self.strategy_name}_tns.csv'))
|
||||
ui_snapshot.show(snapshot_file="", d=snapshot, trade_file=trade_csv, tns_file=tns_csv)
|
||||
|
||||
|
||||
class DataMonitor(QtWidgets.QTableWidget):
|
||||
"""
|
||||
Table monitor for parameters and variables.
|
||||
@ -477,7 +478,7 @@ class SettingEditor(QtWidgets.QDialog):
|
||||
try:
|
||||
value = type_(value_text)
|
||||
except Exception as ex:
|
||||
print(f'{name}数据类型转换未指定')
|
||||
print(f'{name}数据类型转换未指定:{str(ex)}')
|
||||
if isnumber(value_text):
|
||||
value = float(value_text)
|
||||
elif value_text == 'None':
|
||||
@ -489,6 +490,7 @@ class SettingEditor(QtWidgets.QDialog):
|
||||
|
||||
return setting
|
||||
|
||||
|
||||
def isnumber(aString):
|
||||
try:
|
||||
float(aString)
|
||||
|
@ -40,7 +40,6 @@ class RiskManager(QtWidgets.QDialog):
|
||||
self.trade_hold_active_limit_spin = RiskManagerSpinBox()
|
||||
self.trade_hold_percent_limit_spin = RiskManagerSpinBox()
|
||||
|
||||
|
||||
save_button = QtWidgets.QPushButton("保存")
|
||||
save_button.clicked.connect(self.save_setting)
|
||||
|
||||
|
@ -5,3 +5,5 @@ HEIGHT_LIST = [3, 5, 10, 'K3', 'K5', 'K10']
|
||||
|
||||
FUTURE_RENKO_DB_NAME = 'FutureRenko'
|
||||
STOCK_RENKO_DB_NAME = 'StockRenko'
|
||||
CRYPTO_RENKO_DB_NAME= 'CryptoRenko'
|
||||
|
||||
|
@ -26,6 +26,17 @@ stock_type_map = {
|
||||
}
|
||||
STOCK_BASE_FILE = 'stock_base.pkb2'
|
||||
|
||||
# get_stock_base 返回数据格式
|
||||
# vt_symbol: {
|
||||
# 'exchange': 交易所代码
|
||||
# 'code': 股票代码
|
||||
# 'name': 中文名
|
||||
# 'ipo_date': 上市日期
|
||||
# 'out_date': 退市日期
|
||||
# '类型': 股票,指数,其他
|
||||
# 'type': stock_cn, index_cn,etf_cn,bond_cn,cb_cn
|
||||
# 'status': '上市' '退市'
|
||||
# }
|
||||
|
||||
def get_stock_base():
|
||||
""" 获取股票基础信息"""
|
||||
|
@ -46,7 +46,6 @@ NUM_MINUTE_MAPPING['1day'] = 60 * 5.5 # 股票,收盘时间是15:00,开
|
||||
# 常量
|
||||
QSIZE = 800
|
||||
|
||||
|
||||
# 通达信 <=> 交易所代码 映射
|
||||
TDX_VN_STOCK_MARKET_MAP = {
|
||||
TDXParams.MARKET_SH: Exchange.SSE, # 1: 上交所
|
||||
@ -531,8 +530,10 @@ class TdxStockData(object):
|
||||
self.connect()
|
||||
|
||||
data = pd.concat(
|
||||
[pd.concat([self.api.to_df(self.api.get_security_list(j, i * 1000)).assign(sse='sz' if j == 0 else 'sh').set_index(
|
||||
['code', 'sse'], drop=False) for i in range(int(self.api.get_security_count(j) / 1000) + 1)], axis=0) for j
|
||||
[pd.concat(
|
||||
[self.api.to_df(self.api.get_security_list(j, i * 1000)).assign(sse='sz' if j == 0 else 'sh').set_index(
|
||||
['code', 'sse'], drop=False) for i in range(int(self.api.get_security_count(j) / 1000) + 1)],
|
||||
axis=0) for j
|
||||
in range(2)], axis=0)
|
||||
sz = data.query('sse=="sz"')
|
||||
sh = data.query('sse=="sh"')
|
||||
@ -575,7 +576,8 @@ class TdxStockData(object):
|
||||
|
||||
def get_stock_quotes_by_type(self, stock_type):
|
||||
"""根据股票代码类型,获取其最新行情"""
|
||||
stock_list = [(stock.get('market_id'), stock.get('code')) for stock in self.symbol_dict.values() if stock.get('stock_type') == stock_type]
|
||||
stock_list = [(stock.get('market_id'), stock.get('code')) for stock in self.symbol_dict.values() if
|
||||
stock.get('stock_type') == stock_type]
|
||||
|
||||
num_per_count = 60
|
||||
results = []
|
||||
|
@ -18,12 +18,12 @@ t2 = FakeStrategy()
|
||||
api_01 = TdxFutureData(strategy=t1)
|
||||
|
||||
# 获取所有市场信息
|
||||
markets = api_01.get_markets()
|
||||
str_markets = json.dumps(markets, indent=1, ensure_ascii=False)
|
||||
print(u'{}'.format(str_markets))
|
||||
#markets = api_01.get_markets()
|
||||
#str_markets = json.dumps(markets, indent=1, ensure_ascii=False)
|
||||
#print(u'{}'.format(str_markets))
|
||||
|
||||
# 获取所有的期货合约明细
|
||||
api_01.qry_instrument()
|
||||
#api_01.qry_instrument()
|
||||
|
||||
# 获取某个合约得最新价
|
||||
#price = api_01.get_price('rb2010')
|
||||
@ -64,8 +64,8 @@ corr_rate = round(abs(corr.iloc[0, 1]) * 100, 2)
|
||||
# api_01.get_bars('IF99', period='1min', callback=t1.display_bar, bar_freq=1)
|
||||
|
||||
# 获取bar,只返回 list[dict]
|
||||
"""
|
||||
result, bars = api_01.get_bars('IF99', period='1min', return_bar=False)
|
||||
|
||||
result, bars = api_01.get_bars('SA2101', period='1min', return_bar=False)
|
||||
if result:
|
||||
print('前十根bar')
|
||||
for bar in bars[0:10]:
|
||||
@ -73,15 +73,15 @@ if result:
|
||||
print('后十根bar')
|
||||
for bar in bars[-10:]:
|
||||
print(bar)
|
||||
"""
|
||||
|
||||
# result,datas = api_01.get_transaction_data(symbol='ni1905')
|
||||
# api_02 = TdxFutureData(t2)
|
||||
# api_02.get_bars('IF99', period='1min', callback=t1.display_bar)
|
||||
|
||||
# 获取当前交易日分时数据
|
||||
ret,result = api_01.get_transaction_data('NI99')
|
||||
for r in result[0:10] + result[-10:]:
|
||||
print(r)
|
||||
#ret,result = api_01.get_transaction_data('NI99')
|
||||
#for r in result[0:10] + result[-10:]:
|
||||
# print(r)
|
||||
|
||||
# 获取历史分时数据
|
||||
# ret, result = api_01.get_history_transaction_data('RB99', '20190109')
|
||||
|
@ -74,11 +74,13 @@ class DataDownloader:
|
||||
if isinstance(start_dt, datetime):
|
||||
self._start_dt_nano = int(start_dt.timestamp() * 1e9)
|
||||
else:
|
||||
self._start_dt_nano = _get_trading_day_start_time(int(datetime(start_dt.year, start_dt.month, start_dt.day).timestamp()) * 1000000000)
|
||||
self._start_dt_nano = _get_trading_day_start_time(
|
||||
int(datetime(start_dt.year, start_dt.month, start_dt.day).timestamp()) * 1000000000)
|
||||
if isinstance(end_dt, datetime):
|
||||
self._end_dt_nano = int(end_dt.timestamp() * 1e9)
|
||||
else:
|
||||
self._end_dt_nano = _get_trading_day_end_time(int(datetime(end_dt.year, end_dt.month, end_dt.day).timestamp()) * 1000000000)
|
||||
self._end_dt_nano = _get_trading_day_end_time(
|
||||
int(datetime(end_dt.year, end_dt.month, end_dt.day).timestamp()) * 1000000000)
|
||||
self._current_dt_nano = self._start_dt_nano
|
||||
self._symbol_list = symbol_list if isinstance(symbol_list, list) else [symbol_list]
|
||||
# 检查合约代码是否存在
|
||||
|
@ -37,6 +37,7 @@ tick_csv_header = [
|
||||
"bid_price5", "bid_volume5", "ask_price5", "ask_volume5"
|
||||
]
|
||||
|
||||
|
||||
@lru_cache(maxsize=9999)
|
||||
def to_vt_symbol(tq_symbol: str) -> str:
|
||||
""""""
|
||||
@ -235,7 +236,6 @@ class TqFutureData():
|
||||
|
||||
return bars
|
||||
|
||||
|
||||
def get_ticks(self, vt_symbol: str, start_date: datetime, end_date: datetime = None):
|
||||
"""获取历史tick"""
|
||||
|
||||
@ -352,7 +352,3 @@ if __name__ == '__main__':
|
||||
bars = tqsdk.get_bars(vt_symbol='ni2011.SHFE')
|
||||
print(bars[0])
|
||||
print(bars[-1])
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -180,6 +180,7 @@ TQ2VT_TYPE = {
|
||||
"OPTION": Product.OPTION,
|
||||
}
|
||||
|
||||
|
||||
@lru_cache(maxsize=9999)
|
||||
def vt_to_tq_symbol(symbol: str, exchange: Exchange) -> str:
|
||||
"""
|
||||
@ -544,6 +545,7 @@ class CtpGateway(BaseGateway):
|
||||
tick = copy(tick)
|
||||
combiner.on_tick(tick)
|
||||
|
||||
|
||||
class CtpMdApi(MdApi):
|
||||
""""""
|
||||
|
||||
@ -984,8 +986,11 @@ class CtpTdApi(TdApi):
|
||||
account.available = round(float(data["Available"]), 7)
|
||||
account.commission = round(float(data['Commission']), 7)
|
||||
account.margin = round(float(data['CurrMargin']), 7)
|
||||
account.close_profit = round(float(data['CloseProfit']), 7)
|
||||
account.holding_profit = round(float(data['PositionProfit']), 7)
|
||||
account.close_profit = round(float(data['CloseProfit']), 7) + round(
|
||||
float(data.get("SpecProductCloseProfit", 0)), 7)
|
||||
account.holding_profit = round(float(data['PositionProfit']), 7) + round(
|
||||
float(data.get("SpecProductPositionProfit", 0)), 7) + round(
|
||||
float(data.get("SpecProductPositionProfitByAlg", 0)), 7)
|
||||
account.trading_day = str(data['TradingDay'])
|
||||
if '-' not in account.trading_day and len(account.trading_day) == 8:
|
||||
account.trading_day = '-'.join(
|
||||
@ -1805,7 +1810,6 @@ class SubMdApi():
|
||||
|
||||
d.update({'open_interest': d.pop('tradingDay', get_trading_date())})
|
||||
|
||||
|
||||
# 常规行情
|
||||
d.update({'open_price': d.pop('openPrice', 0)}) # 今日开盘价
|
||||
d.update({'high_price': d.pop('highPrice', 0)}) # 今日最高价
|
||||
|
@ -17,6 +17,11 @@ from functools import lru_cache
|
||||
from collections import OrderedDict
|
||||
from multiprocessing.dummy import Pool
|
||||
from threading import Thread
|
||||
|
||||
from pytdx.hq import TdxHq_API
|
||||
from pytdx.config.hosts import hq_hosts
|
||||
from pytdx.params import TDXParams
|
||||
|
||||
from vnpy.event import EventEngine
|
||||
from vnpy.trader.event import EVENT_TIMER
|
||||
from vnpy.trader.constant import (
|
||||
@ -45,6 +50,9 @@ from vnpy.trader.object import (
|
||||
from vnpy.trader.utility import get_folder_path, print_dict, extract_vt_symbol, get_stock_exchange, append_data
|
||||
from vnpy.data.tdx.tdx_common import get_stock_type_sz, get_stock_type_sh
|
||||
|
||||
# 通达信股票行情
|
||||
from vnpy.data.tdx.tdx_common import get_cache_config, get_tdx_market_code
|
||||
|
||||
# 代码 <=> 中文名称
|
||||
symbol_name_map: Dict[str, str] = {}
|
||||
# 代码 <=> 交易所
|
||||
@ -303,11 +311,6 @@ STATUS_PB2VT: Dict[str, Status] = {
|
||||
}
|
||||
|
||||
STOCK_CONFIG_FILE = 'tdx_stock_config.pkb2'
|
||||
from pytdx.hq import TdxHq_API
|
||||
# 通达信股票行情
|
||||
from vnpy.data.tdx.tdx_common import get_cache_config, get_tdx_market_code
|
||||
from pytdx.config.hosts import hq_hosts
|
||||
from pytdx.params import TDXParams
|
||||
|
||||
|
||||
class PbGateway(BaseGateway):
|
||||
@ -1654,7 +1657,8 @@ class PbTdApi(object):
|
||||
order.status = Status.REJECTED
|
||||
self.gateway.write_log(f'dbf批量下单,委托被拒:{order.__dict__}')
|
||||
self.gateway.order_manager.on_order(order)
|
||||
self.gateway.write_error(msg=f'{order.direction.value},{order.vt_symbol},{err_msg}', error={"ErrorID": err_id, "ErrorMsg": "委托失败"})
|
||||
self.gateway.write_error(msg=f'{order.direction.value},{order.vt_symbol},{err_msg}',
|
||||
error={"ErrorID": err_id, "ErrorMsg": "委托失败"})
|
||||
|
||||
if sys_orderid != '0':
|
||||
self.gateway.order_manager.update_orderid_map(local_orderid=local_orderid,
|
||||
@ -1933,7 +1937,6 @@ class PbTdApi(object):
|
||||
'{}{}.dbf'.format(PB_FILE_NAMES.get('cancel_order'),
|
||||
self.trading_date)))
|
||||
|
||||
|
||||
# 打开dbf文件=》table
|
||||
table = dbf.Table(dbf_file)
|
||||
# 读取、写入模式
|
||||
@ -2069,7 +2072,7 @@ class TqMdApi():
|
||||
return
|
||||
try:
|
||||
from tqsdk import TqApi
|
||||
self.api = TqApi(_stock=True)
|
||||
self.api = TqApi(_stock=True, url="wss://u.shinnytech.com/t/nfmd/front/mobile")
|
||||
except Exception as e:
|
||||
self.gateway.write_log(f'天勤股票行情API接入异常:'.format(str(e)))
|
||||
self.gateway.write_log(traceback.format_exc())
|
||||
@ -2203,4 +2206,3 @@ class TqMdApi():
|
||||
self.update_thread.join()
|
||||
except Exception as e:
|
||||
self.gateway.write_log('退出天勤行情api异常:{}'.format(str(e)))
|
||||
|
||||
|
@ -175,6 +175,7 @@ TQ2VT_TYPE = {
|
||||
"OPTION": Product.OPTION,
|
||||
}
|
||||
|
||||
|
||||
@lru_cache(maxsize=9999)
|
||||
def vt_to_tq_symbol(symbol: str, exchange: Exchange) -> str:
|
||||
"""
|
||||
@ -537,6 +538,7 @@ class RohonGateway(BaseGateway):
|
||||
tick = copy(tick)
|
||||
combiner.on_tick(tick)
|
||||
|
||||
|
||||
class RohonMdApi(MdApi):
|
||||
""""""
|
||||
|
||||
@ -1762,7 +1764,7 @@ class SubMdApi():
|
||||
return d
|
||||
symbol = d.get('symbol')
|
||||
exchange = d.get('exchange')
|
||||
vtSymbol = d.pop('vtSymbol', symbol)
|
||||
d.pop('vtSymbol', None)
|
||||
if '.' not in symbol:
|
||||
d.update({'vt_symbol': f'{symbol}.{exchange}'})
|
||||
else:
|
||||
@ -1776,7 +1778,6 @@ class SubMdApi():
|
||||
|
||||
d.update({'open_interest': d.pop('tradingDay', get_trading_date())})
|
||||
|
||||
|
||||
# 常规行情
|
||||
d.update({'open_price': d.pop('openPrice', 0)}) # 今日开盘价
|
||||
d.update({'high_price': d.pop('highPrice', 0)}) # 今日最高价
|
||||
@ -1960,7 +1961,7 @@ class TqMdApi():
|
||||
def query_contracts(self) -> None:
|
||||
""""""
|
||||
self.all_instruments = [
|
||||
v for k, v in self.api._data["quotes"].items() if v["expired"] == False
|
||||
v for k, v in self.api._data["quotes"].items() if not v["expired"]
|
||||
]
|
||||
for contract in self.all_instruments:
|
||||
if (
|
||||
|
@ -71,7 +71,6 @@ from vnpy.trader.utility import (
|
||||
)
|
||||
from vnpy.trader.event import EVENT_TIMER
|
||||
|
||||
|
||||
STATUS_SOPT2VT = {
|
||||
THOST_FTDC_OAS_Submitted: Status.SUBMITTING,
|
||||
THOST_FTDC_OAS_Accepted: Status.SUBMITTING,
|
||||
@ -127,6 +126,7 @@ symbol_name_map = {}
|
||||
symbol_size_map = {}
|
||||
option_name_map = {}
|
||||
|
||||
|
||||
class SoptGateway(BaseGateway):
|
||||
"""
|
||||
VN Trader Gateway for SOPT .
|
||||
@ -306,7 +306,6 @@ class SoptGateway(BaseGateway):
|
||||
self.query_functions = [self.query_account, self.query_position]
|
||||
self.event_engine.register(EVENT_TIMER, self.process_timer_event)
|
||||
|
||||
|
||||
def on_custom_tick(self, tick):
|
||||
"""推送自定义合约行情"""
|
||||
# 自定义合约行情
|
||||
@ -408,6 +407,7 @@ class SoptMdApi(MdApi):
|
||||
ask_price_1=data["AskPrice1"],
|
||||
bid_volume_1=data["BidVolume1"],
|
||||
ask_volume_1=data["AskVolume1"],
|
||||
trading_day=dt.strftime('%Y-%m-%d'),
|
||||
gateway_name=self.gateway_name
|
||||
)
|
||||
|
||||
@ -597,7 +597,8 @@ class SoptTdApi(TdApi):
|
||||
)
|
||||
self.gateway.on_order(order)
|
||||
|
||||
self.gateway.write_error(f"交易委托失败:{symbol} {order.direction.value} {order.offset.value} {order.price}, {order.volume}", error)
|
||||
self.gateway.write_error(
|
||||
f"交易委托失败:{symbol} {order.direction.value} {order.offset.value} {order.price}, {order.volume}", error)
|
||||
|
||||
def onRspOrderAction(self, data: dict, error: dict, reqid: int, last: bool):
|
||||
""""""
|
||||
@ -682,16 +683,20 @@ class SoptTdApi(TdApi):
|
||||
# 重新累计多头期权动态权益
|
||||
if position.direction == Direction.LONG:
|
||||
if self.long_option_cost is None:
|
||||
self.long_option_cost = position.cur_price * position.volume * symbol_size_map.get(position.symbol, 0)
|
||||
self.long_option_cost = position.cur_price * position.volume * symbol_size_map.get(
|
||||
position.symbol, 0)
|
||||
else:
|
||||
self.long_option_cost += position.cur_price * position.volume * symbol_size_map.get(position.symbol, 0)
|
||||
self.long_option_cost += position.cur_price * position.volume * symbol_size_map.get(
|
||||
position.symbol, 0)
|
||||
|
||||
# 重新累计空头期权动态权益
|
||||
if position.direction == Direction.SHORT:
|
||||
if self.short_option_cost is None:
|
||||
self.short_option_cost = position.cur_price * position.volume * symbol_size_map.get(position.symbol, 0)
|
||||
self.short_option_cost = position.cur_price * position.volume * symbol_size_map.get(
|
||||
position.symbol, 0)
|
||||
else:
|
||||
self.short_option_cost += position.cur_price * position.volume * symbol_size_map.get(position.symbol, 0)
|
||||
self.short_option_cost += position.cur_price * position.volume * symbol_size_map.get(
|
||||
position.symbol, 0)
|
||||
|
||||
self.gateway.on_position(position)
|
||||
|
||||
@ -723,7 +728,8 @@ class SoptTdApi(TdApi):
|
||||
account.commission = round(float(data['Commission']), 7) + round(float(data['SpecProductCommission']), 7)
|
||||
account.margin = round(float(data['CurrMargin']), 7)
|
||||
account.close_profit = round(float(data['CloseProfit']), 7) + round(float(data['SpecProductCloseProfit']), 7)
|
||||
account.holding_profit = round(float(data['PositionProfit']), 7) + round(float(data['SpecProductPositionProfit']), 7)
|
||||
account.holding_profit = round(float(data['PositionProfit']), 7) + round(
|
||||
float(data['SpecProductPositionProfit']), 7)
|
||||
|
||||
account.trading_day = str(data.get('TradingDay', datetime.now().strftime('%Y-%m-%d')))
|
||||
if '-' not in account.trading_day and len(account.trading_day) == 8:
|
||||
|
@ -128,12 +128,13 @@ symbol_name_map: Dict[str, str] = {}
|
||||
# 代码 <=> 交易所
|
||||
symbol_exchange_map: Dict[str, Exchange] = {}
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def get_vt_symbol_name(vt_symbol):
|
||||
return symbol_name_map.get(vt_symbol, vt_symbol.split('.')[0])
|
||||
|
||||
class XtpGateway(BaseGateway):
|
||||
|
||||
class XtpGateway(BaseGateway):
|
||||
default_setting: Dict[str, Any] = {
|
||||
"账号": "",
|
||||
"密码": "",
|
||||
|
@ -165,6 +165,7 @@ class Interval(Enum):
|
||||
WEEKLY = "w"
|
||||
RENKO = 'renko'
|
||||
|
||||
|
||||
class StockType(Enum):
|
||||
"""股票类型(tdx)"""
|
||||
STOCK = 'stock_cn' # 股票
|
||||
|
@ -766,6 +766,7 @@ class OmsEngine(BaseEngine):
|
||||
"""根据主动腿/被动腿symbol,获取自定义套利对的symbol list"""
|
||||
return self.symbol_spd_maping.get(symbol, [])
|
||||
|
||||
|
||||
class CustomContract(object):
|
||||
"""
|
||||
定制合约
|
||||
|
@ -209,6 +209,7 @@ class TradeData(BaseData):
|
||||
self.vt_tradeid = f"{self.gateway_name}.{self.tradeid}"
|
||||
self.vt_accountid = f"{self.gateway_name}.{self.accountid}"
|
||||
|
||||
|
||||
@dataclass
|
||||
class PositionData(BaseData):
|
||||
"""
|
||||
@ -238,6 +239,7 @@ class PositionData(BaseData):
|
||||
if self.name == "":
|
||||
self.name = self.vt_symbol
|
||||
|
||||
|
||||
@dataclass
|
||||
class AccountData(BaseData):
|
||||
"""
|
||||
|
@ -9,7 +9,6 @@ from copy import copy
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
from vnpy.event import Event, EventEngine
|
||||
from ..constant import Direction, Exchange, Offset, OrderType
|
||||
from ..engine import MainEngine
|
||||
|
@ -14,15 +14,16 @@ import requests
|
||||
import sys
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from functools import wraps
|
||||
# from functools import wraps
|
||||
from vnpy.trader.utility import print_dict
|
||||
|
||||
global wechat_lock
|
||||
wechat_lock = Lock()
|
||||
|
||||
# 这里可以设置UIDS, 多个人可同时接收
|
||||
UIDS = ['UID_kZguGPBQPWn41Ni9FK4CgPts2KjU']
|
||||
UIDS = ['UID_kZguGPBQPWn41Ni9FK4CgPts2Kjx']
|
||||
|
||||
APP_TOKEN = 'AT_aDuiQu41dmAQV2vUMXOaaTDrWyhKJN2z'
|
||||
APP_TOKEN = 'AT_aDuiQu41dmAQV2vUMXOaaTDrWyhKJN2x'
|
||||
|
||||
|
||||
class wechat_thread(Thread):
|
||||
@ -42,7 +43,7 @@ class wechat_thread(Thread):
|
||||
self.topic_ids = topic_ids
|
||||
self.url = url
|
||||
self.lock = wechat_lock
|
||||
self.app_token = app_token if len(app_token) > 0 else APP_TOKEN
|
||||
self.app_token = app_token if app_token is not None and len(app_token) > 0 else APP_TOKEN
|
||||
|
||||
def run(self):
|
||||
if self.content is None or len(self.content) == 0:
|
||||
@ -61,7 +62,7 @@ class wechat_thread(Thread):
|
||||
if not response.get('success', False):
|
||||
print(response)
|
||||
except Exception as e:
|
||||
print("{} wechat_thread sent failed! ex:{},trace:{}".format(datetime.now(), str(e), traceback.format_exc()),
|
||||
print("{} 微信发送异常 ex:{},trace:{}".format(datetime.now(), str(e), traceback.format_exc()),
|
||||
file=sys.stderr)
|
||||
return
|
||||
|
||||
@ -84,7 +85,8 @@ def send_wx_msg(*args, **kwargs):
|
||||
|
||||
try:
|
||||
# 如果存在华富资产的微信模块,则使用
|
||||
from vnpy.trader.util_huafu import sendWeChatMsg, WECHAT_URL,WECHAT_GROUP, WECHAT_LEVEL_INFO, WECHAT_MSG_TYPE_ALERT
|
||||
from vnpy.trader.util_huafu import sendWeChatMsg, WECHAT_URL, WECHAT_GROUP, WECHAT_LEVEL_INFO, \
|
||||
WECHAT_MSG_TYPE_ALERT
|
||||
target = kwargs.get('target', 'XXX')
|
||||
sendWeChatMsg(content=content,
|
||||
target=WECHAT_GROUP.get(target),
|
||||
@ -93,6 +95,7 @@ def send_wx_msg(*args, **kwargs):
|
||||
msg_type=kwargs.get('msg_type', WECHAT_MSG_TYPE_ALERT))
|
||||
return
|
||||
except Exception as ex:
|
||||
print(f'发送微信异常:{str(ex)}', file=sys.stderr)
|
||||
pass
|
||||
|
||||
# dict => str, none str => str
|
||||
@ -114,6 +117,7 @@ def send_wx_msg(*args, **kwargs):
|
||||
# t.run()
|
||||
t.start()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
text = u'微信测试标题!!!!\n第二行'
|
||||
|
||||
|
@ -163,6 +163,7 @@ def get_trading_date(dt: datetime = None):
|
||||
else:
|
||||
return dt.strftime('%Y-%m-%d')
|
||||
|
||||
|
||||
def extract_vt_symbol(vt_symbol: str) -> Tuple[str, Exchange]:
|
||||
"""
|
||||
:return: (symbol, exchange)
|
||||
@ -328,6 +329,7 @@ def get_digits(value: float) -> int:
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
def print_dict(d: dict):
|
||||
"""返回dict的字符串类型"""
|
||||
return '\n'.join([f'{key}:{d[key]}' for key in sorted(d.keys())])
|
||||
@ -356,6 +358,7 @@ def get_csv_last_dt(file_name, dt_index=0, dt_format='%Y-%m-%d %H:%M:%S', line_l
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
def append_data(file_name: str, dict_data: dict, field_names: list = [], auto_header=True, encoding='utf8'):
|
||||
"""
|
||||
添加数据到csv文件中
|
||||
@ -669,6 +672,7 @@ def load_data_from_pkb2(pkb2_file_name):
|
||||
data = pickle.load(f)
|
||||
return data
|
||||
|
||||
|
||||
def save_data_to_pkb2(data: Any, pkb2_file_name):
|
||||
"""保存本地缓存的配置地址信息"""
|
||||
with bz2.BZ2File(pkb2_file_name, 'wb') as f:
|
||||
|
Loading…
Reference in New Issue
Block a user