[update] 基础组件更新
This commit is contained in:
parent
344f877bda
commit
98ab549e0d
@ -3,6 +3,7 @@
|
|||||||
下载通达信股票合约1分钟&日线bar => vnpy项目目录/bar_data/
|
下载通达信股票合约1分钟&日线bar => vnpy项目目录/bar_data/
|
||||||
上海股票 => SSE子目录
|
上海股票 => SSE子目录
|
||||||
深圳股票 => SZSE子目录
|
深圳股票 => SZSE子目录
|
||||||
|
修改为多进程模式
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -10,6 +11,10 @@ import csv
|
|||||||
import json
|
import json
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
from multiprocessing import Pool
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
|
from copy import copy
|
||||||
|
|
||||||
vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||||
if vnpy_root not in sys.path:
|
if vnpy_root not in sys.path:
|
||||||
@ -35,15 +40,21 @@ api_01 = TdxStockData()
|
|||||||
# 额外需要数据下载的基金列表
|
# 额外需要数据下载的基金列表
|
||||||
stock_list = load_json('stock_list.json')
|
stock_list = load_json('stock_list.json')
|
||||||
|
|
||||||
|
# 强制更新缓存
|
||||||
|
api_01.cache_config()
|
||||||
symbol_dict = api_01.symbol_dict
|
symbol_dict = api_01.symbol_dict
|
||||||
|
#
|
||||||
|
# thread_executor = ThreadPoolExecutor(max_workers=1)
|
||||||
|
# thread_tasks = []
|
||||||
|
|
||||||
# 下载所有的股票数据
|
|
||||||
num_stocks = 0
|
def refill(symbol_info):
|
||||||
for period in ['1min', '1day']:
|
period = symbol_info['period']
|
||||||
for symbol in symbol_dict.keys():
|
progress = symbol_info['progress']
|
||||||
symbol_info = symbol_dict[symbol]
|
# print("{}_{}".format(period, symbol_info['code']))
|
||||||
|
# return
|
||||||
stock_code = symbol_info['code']
|
stock_code = symbol_info['code']
|
||||||
if ('stock_type' in symbol_info.keys() and symbol_info['stock_type'] in ['stock_cn', 'cb_cn']) or stock_code in stock_list:
|
|
||||||
# if stock_code in stock_list:
|
# if stock_code in stock_list:
|
||||||
# print(symbol_info['code'])
|
# print(symbol_info['code'])
|
||||||
if symbol_info['exchange'] == 'SZSE':
|
if symbol_info['exchange'] == 'SZSE':
|
||||||
@ -52,9 +63,8 @@ for period in ['1min', '1day']:
|
|||||||
else:
|
else:
|
||||||
exchange_name = '上交所'
|
exchange_name = '上交所'
|
||||||
exchange = Exchange.SSE
|
exchange = Exchange.SSE
|
||||||
else:
|
|
||||||
continue
|
# num_stocks += 1
|
||||||
num_stocks += 1
|
|
||||||
|
|
||||||
stock_name = symbol_info.get('name')
|
stock_name = symbol_info.get('name')
|
||||||
print(f'开始更新:{exchange_name}/{stock_name}, 代码:{stock_code}')
|
print(f'开始更新:{exchange_name}/{stock_name}, 代码:{stock_code}')
|
||||||
@ -62,7 +72,8 @@ for period in ['1min', '1day']:
|
|||||||
if not os.path.exists(bar_file_folder):
|
if not os.path.exists(bar_file_folder):
|
||||||
os.makedirs(bar_file_folder)
|
os.makedirs(bar_file_folder)
|
||||||
# csv数据文件名
|
# csv数据文件名
|
||||||
bar_file_path = os.path.abspath(os.path.join(bar_file_folder, f'{stock_code}_{period[0:2]}.csv'))
|
p_name = period.replace('min', 'm').replace('day', 'd').replace('hour', 'h')
|
||||||
|
bar_file_path = os.path.abspath(os.path.join(bar_file_folder, f'{stock_code}_{p_name}.csv'))
|
||||||
|
|
||||||
# 如果文件存在,
|
# 如果文件存在,
|
||||||
if os.path.exists(bar_file_path):
|
if os.path.exists(bar_file_path):
|
||||||
@ -73,11 +84,12 @@ for period in ['1min', '1day']:
|
|||||||
|
|
||||||
if last_dt:
|
if last_dt:
|
||||||
start_dt = last_dt - timedelta(days=1)
|
start_dt = last_dt - timedelta(days=1)
|
||||||
print(f'文件{bar_file_path}存在,最后时间:{start_date}')
|
print(f'文件{bar_file_path}存在,最后时间:{start_dt}')
|
||||||
else:
|
else:
|
||||||
start_dt = datetime.strptime(start_date, '%Y%m%d')
|
start_dt = datetime.strptime(start_date, '%Y%m%d')
|
||||||
print(f'文件{bar_file_path}不存在,或读取最后记录错误,开始时间:{start_date}')
|
print(f'文件{bar_file_path}不存在,或读取最后记录错误,开始时间:{start_date}')
|
||||||
|
|
||||||
|
d1 = datetime.now()
|
||||||
result, bars = api_01.get_bars(symbol=stock_code,
|
result, bars = api_01.get_bars(symbol=stock_code,
|
||||||
period=period,
|
period=period,
|
||||||
callback=None,
|
callback=None,
|
||||||
@ -85,8 +97,9 @@ for period in ['1min', '1day']:
|
|||||||
return_bar=False)
|
return_bar=False)
|
||||||
# [dict] => dataframe
|
# [dict] => dataframe
|
||||||
if not result or len(bars) == 0:
|
if not result or len(bars) == 0:
|
||||||
continue
|
return
|
||||||
|
|
||||||
|
need_resample = False
|
||||||
# 全新数据
|
# 全新数据
|
||||||
if last_dt is None:
|
if last_dt is None:
|
||||||
data_df = pd.DataFrame(bars)
|
data_df = pd.DataFrame(bars)
|
||||||
@ -95,7 +108,10 @@ for period in ['1min', '1day']:
|
|||||||
# print(data_df.head())
|
# print(data_df.head())
|
||||||
print(data_df.tail())
|
print(data_df.tail())
|
||||||
data_df.to_csv(bar_file_path, index=True)
|
data_df.to_csv(bar_file_path, index=True)
|
||||||
print(f'首次更新{stock_code} {stock_name}数据 => 文件{bar_file_path}')
|
d2 = datetime.now()
|
||||||
|
microseconds = (d1 - d1).microseconds
|
||||||
|
print(f'{progress}% 首次更新{stock_code} {stock_name}数据 {microseconds} 毫秒=> 文件{bar_file_path}')
|
||||||
|
need_resample = True
|
||||||
|
|
||||||
# 增量更新
|
# 增量更新
|
||||||
else:
|
else:
|
||||||
@ -119,13 +135,68 @@ for period in ['1min', '1day']:
|
|||||||
continue
|
continue
|
||||||
bar_count += 1
|
bar_count += 1
|
||||||
writer.writerow(bar)
|
writer.writerow(bar)
|
||||||
|
if not need_resample:
|
||||||
|
need_resample = True
|
||||||
|
d2 = datetime.now()
|
||||||
|
microseconds = round((d2 - d1).microseconds / 100, 0)
|
||||||
|
print(f'{progress}%,更新{stock_code} {stock_name} 数据 {microseconds}毫秒 => 文件{bar_file_path}, 最后记录:{bars[-1]}')
|
||||||
|
|
||||||
print(f'更新{stock_code} {stock_name} 数据 => 文件{bar_file_path}, 最后记录:{bars[-1]}')
|
# 采用多线程方式输出 5、15、30分钟的数据
|
||||||
|
# if period == '1min' and need_resample:
|
||||||
|
# task = thread_executor.submit(resample, stock_code, exchange, [5, 15, 30])
|
||||||
|
# thread_tasks.append(task)
|
||||||
|
|
||||||
# 输出 5、15、30分钟的数据
|
|
||||||
if period == '1min':
|
|
||||||
out_files, err_msg = resample_bars_file(vnpy_root=vnpy_root, symbol=stock_code, exchange=exchange, x_mins=[5,15,30])
|
|
||||||
|
|
||||||
msg = 'tdx股票数据补充完毕: num_stocks={}'.format(num_stocks)
|
def resample(symbol, exchange, x_mins=[5, 15, 30]):
|
||||||
send_wx_msg(content=msg)
|
"""
|
||||||
os._exit(0)
|
更新多周期文件
|
||||||
|
:param symbol:
|
||||||
|
:param exchange:
|
||||||
|
:param x_mins:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
d1 = datetime.now()
|
||||||
|
out_files, err_msg = resample_bars_file(vnpy_root=vnpy_root,
|
||||||
|
symbol=symbol,
|
||||||
|
exchange=exchange,
|
||||||
|
x_mins=x_mins)
|
||||||
|
d2 = datetime.now()
|
||||||
|
microseconds = round((d2 - d1).microseconds / 100, 0)
|
||||||
|
if len(err_msg) > 0:
|
||||||
|
print(err_msg, file=sys.stderr)
|
||||||
|
|
||||||
|
if out_files:
|
||||||
|
print(f'{microseconds}毫秒,生成 =>{out_files}')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
# 下载所有的股票数据
|
||||||
|
num_progress = 0
|
||||||
|
total_tasks = len(symbol_dict.keys()) * 2
|
||||||
|
tasks = []
|
||||||
|
for period in ['1min', '5min', '15min', '30min', '1hour', '1day']:
|
||||||
|
for symbol in symbol_dict.keys():
|
||||||
|
info = copy(symbol_dict[symbol])
|
||||||
|
stock_code = info['code']
|
||||||
|
if ('stock_type' in info.keys() and info['stock_type'] in ['stock_cn',
|
||||||
|
'cb_cn']) or stock_code in stock_list:
|
||||||
|
info['period'] = period
|
||||||
|
tasks.append(info)
|
||||||
|
# if len(tasks) > 12:
|
||||||
|
# break
|
||||||
|
|
||||||
|
total_tasks = len(tasks)
|
||||||
|
for task in tasks:
|
||||||
|
num_progress += 1
|
||||||
|
task['progress'] = round(100 * num_progress / total_tasks, 2)
|
||||||
|
|
||||||
|
p = Pool(12)
|
||||||
|
p.map(refill, tasks)
|
||||||
|
p.close()
|
||||||
|
p.join()
|
||||||
|
|
||||||
|
#
|
||||||
|
msg = 'tdx股票数据补充完毕: num_stocks={}'.format(total_tasks)
|
||||||
|
send_wx_msg(content=msg)
|
||||||
|
os._exit(0)
|
||||||
|
@ -1921,7 +1921,7 @@ class BackTestingEngine(object):
|
|||||||
# 返回回测结果
|
# 返回回测结果
|
||||||
d = {}
|
d = {}
|
||||||
d['init_capital'] = self.init_capital
|
d['init_capital'] = self.init_capital
|
||||||
d['profit'] = self.cur_capital - self.init_capital
|
d['profit'] = self.net_capital - self.init_capital
|
||||||
d['net_capital'] = self.net_capital
|
d['net_capital'] = self.net_capital
|
||||||
d['max_capital'] = self.max_net_capital # 取消原 maxCapital
|
d['max_capital'] = self.max_net_capital # 取消原 maxCapital
|
||||||
|
|
||||||
@ -2006,8 +2006,8 @@ class BackTestingEngine(object):
|
|||||||
result_info.update({u'期末资金': d['net_capital']})
|
result_info.update({u'期末资金': d['net_capital']})
|
||||||
self.output(u'期末资金:\t%s' % format_number(d['net_capital']))
|
self.output(u'期末资金:\t%s' % format_number(d['net_capital']))
|
||||||
|
|
||||||
result_info.update({u'平仓盈亏': d['profit']})
|
result_info.update({u'总盈亏': d['profit']})
|
||||||
self.output(u'平仓盈亏:\t%s' % format_number(d['profit']))
|
self.output(u'总盈亏:\t%s' % format_number(d['profit']))
|
||||||
|
|
||||||
result_info.update({u'资金最高净值': d['max_capital']})
|
result_info.update({u'资金最高净值': d['max_capital']})
|
||||||
self.output(u'资金最高净值:\t%s' % format_number(d['max_capital']))
|
self.output(u'资金最高净值:\t%s' % format_number(d['max_capital']))
|
||||||
|
@ -1316,7 +1316,7 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
|
|
||||||
up_grids_info = ""
|
up_grids_info = ""
|
||||||
for grid in list(self.gt.up_grids):
|
for grid in list(self.gt.up_grids):
|
||||||
if not grid.open_status and grid.order_status:
|
if grid.open_status and grid.order_status:
|
||||||
up_grids_info += f'平空中: [已平:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}]\n'
|
up_grids_info += f'平空中: [已平:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}]\n'
|
||||||
if len(grid.order_ids) > 0:
|
if len(grid.order_ids) > 0:
|
||||||
up_grids_info += f'委托单号:{grid.order_ids}'
|
up_grids_info += f'委托单号:{grid.order_ids}'
|
||||||
@ -1333,7 +1333,7 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
|
|
||||||
dn_grids_info = ""
|
dn_grids_info = ""
|
||||||
for grid in list(self.gt.dn_grids):
|
for grid in list(self.gt.dn_grids):
|
||||||
if not grid.open_status and grid.order_status:
|
if grid.open_status and grid.order_status:
|
||||||
dn_grids_info += f'平多中: [已平:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}]\n'
|
dn_grids_info += f'平多中: [已平:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}]\n'
|
||||||
if len(grid.order_ids) > 0:
|
if len(grid.order_ids) > 0:
|
||||||
dn_grids_info += f'委托单号:{grid.order_ids}'
|
dn_grids_info += f'委托单号:{grid.order_ids}'
|
||||||
|
@ -450,6 +450,13 @@ class PortfolioTestingEngine(BackTestingEngine):
|
|||||||
'{}_{}.csv'.format(symbol, tick_date.strftime('%Y%m%d'))))
|
'{}_{}.csv'.format(symbol, tick_date.strftime('%Y%m%d'))))
|
||||||
|
|
||||||
ticks = []
|
ticks = []
|
||||||
|
if not os.path.isfile(file_path):
|
||||||
|
self.write_log(u'{}文件不存在'.format(file_path))
|
||||||
|
file_path = os.path.abspath(
|
||||||
|
os.path.join(
|
||||||
|
tick_folder,
|
||||||
|
tick_date.strftime('%Y%m'),
|
||||||
|
'{}_{}.csv'.format(symbol.lower(), tick_date.strftime('%Y%m%d'))))
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
self.write_log(u'{}文件不存在'.format(file_path))
|
self.write_log(u'{}文件不存在'.format(file_path))
|
||||||
return None
|
return None
|
||||||
@ -589,8 +596,32 @@ class PortfolioTestingEngine(BackTestingEngine):
|
|||||||
time=dt.strftime('%H:%M:%S.%f'),
|
time=dt.strftime('%H:%M:%S.%f'),
|
||||||
trading_day=test_day.strftime('%Y-%m-%d'),
|
trading_day=test_day.strftime('%Y-%m-%d'),
|
||||||
last_price=last_price,
|
last_price=last_price,
|
||||||
volume=tick_data['volume']
|
volume=tick_data['volume'],
|
||||||
|
ask_price_1=float(tick_data.get('ask_price_1',0)),
|
||||||
|
ask_volume_1=int(tick_data.get('ask_volume_1',0)),
|
||||||
|
bid_price_1=float(tick_data.get('bid_price_1',0)),
|
||||||
|
bid_volume_1=int(tick_data.get('bid_volume_1',0))
|
||||||
)
|
)
|
||||||
|
if tick_data.get('ask_price_5',0) > 0:
|
||||||
|
tick.ask_price_2 = float(tick_data.get('ask_price_2',0))
|
||||||
|
tick.ask_volume_2 = int(tick_data.get('ask_volume_2', 0))
|
||||||
|
tick.bid_price_2 = float(tick_data.get('bid_price_2', 0))
|
||||||
|
tick.bid_volume_2 = int(tick_data.get('bid_volume_2', 0))
|
||||||
|
|
||||||
|
tick.ask_price_3 = float(tick_data.get('ask_price_3', 0))
|
||||||
|
tick.ask_volume_3 = int(tick_data.get('ask_volume_3', 0)),
|
||||||
|
tick.bid_price_3 = float(tick_data.get('bid_price_3', 0)),
|
||||||
|
tick.bid_volume_3 = int(tick_data.get('bid_volume_3', 0))
|
||||||
|
|
||||||
|
tick.ask_price_4 = float(tick_data.get('ask_price_4', 0))
|
||||||
|
tick.ask_volume_4 = int(tick_data.get('ask_volume_4', 0)),
|
||||||
|
tick.bid_price_4 = float(tick_data.get('bid_price_4', 0)),
|
||||||
|
tick.bid_volume_4 = int(tick_data.get('bid_volume_4', 0))
|
||||||
|
|
||||||
|
tick.ask_price_5 = float(tick_data.get('ask_price_5', 0))
|
||||||
|
tick.ask_volume_5 = int(tick_data.get('ask_volume_5', 0)),
|
||||||
|
tick.bid_price_5 = float(tick_data.get('bid_price_5', 0)),
|
||||||
|
tick.bid_volume_5 = int(tick_data.get('bid_volume_5', 0))
|
||||||
|
|
||||||
self.new_tick(tick)
|
self.new_tick(tick)
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@ import sys
|
|||||||
from abc import ABC
|
from abc import ABC
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from logging import INFO, ERROR
|
from logging import INFO, ERROR
|
||||||
|
import json
|
||||||
|
import numpy as np
|
||||||
|
import datetime
|
||||||
from vnpy.trader.constant import Direction # noqa
|
from vnpy.trader.constant import Direction # noqa
|
||||||
|
|
||||||
|
|
||||||
@ -71,3 +74,20 @@ class CtaComponent(ABC):
|
|||||||
self.strategy.write_log(msg=content, level=level)
|
self.strategy.write_log(msg=content, level=level)
|
||||||
else:
|
else:
|
||||||
print(content, file=sys.stderr)
|
print(content, file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
class MyEncoder(json.JSONEncoder):
|
||||||
|
"""
|
||||||
|
自定义转换器,处理np,datetime等不能被json转换得问题
|
||||||
|
"""
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj, np.integer):
|
||||||
|
return int(obj)
|
||||||
|
elif isinstance(obj, np.floating):
|
||||||
|
return float(obj)
|
||||||
|
elif isinstance(obj, np.ndarray):
|
||||||
|
return obj.tolist()
|
||||||
|
elif isinstance(obj, datetime):
|
||||||
|
return obj.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
else:
|
||||||
|
return super(MyEncoder, self).default(obj)
|
||||||
|
@ -10,7 +10,7 @@ import traceback
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from vnpy.trader.utility import get_folder_path
|
from vnpy.trader.utility import get_folder_path
|
||||||
from vnpy.component.base import Direction, CtaComponent
|
from vnpy.component.base import Direction, CtaComponent,MyEncoder
|
||||||
|
|
||||||
"""
|
"""
|
||||||
网格交易,用于套利单
|
网格交易,用于套利单
|
||||||
@ -894,7 +894,7 @@ class CtaGridTrade(CtaComponent):
|
|||||||
data = self.to_json()
|
data = self.to_json()
|
||||||
|
|
||||||
with open(grid_json_file, 'w', encoding='utf8') as f:
|
with open(grid_json_file, 'w', encoding='utf8') as f:
|
||||||
json_data = json.dumps(data, indent=4, ensure_ascii=False)
|
json_data = json.dumps(data, indent=4, ensure_ascii=False, cls=MyEncoder)
|
||||||
f.write(json_data)
|
f.write(json_data)
|
||||||
|
|
||||||
self.write_log(u'GrideTrade保存文件{}完成'.format(grid_json_file))
|
self.write_log(u'GrideTrade保存文件{}完成'.format(grid_json_file))
|
||||||
|
@ -28,8 +28,9 @@ from vnpy.component.base import (
|
|||||||
MARKET_ZJ)
|
MARKET_ZJ)
|
||||||
from vnpy.component.cta_period import CtaPeriod, Period
|
from vnpy.component.cta_period import CtaPeriod, Period
|
||||||
from vnpy.trader.object import BarData, TickData
|
from vnpy.trader.object import BarData, TickData
|
||||||
from vnpy.trader.constant import Interval, Color
|
from vnpy.trader.constant import Interval, Color, ChanSignals
|
||||||
from vnpy.trader.utility import round_to, get_trading_date, get_underlying_symbol
|
from vnpy.trader.utility import round_to, get_trading_date, get_underlying_symbol
|
||||||
|
from vnpy.component.cta_utility import check_chan_xt,check_chan_xt_three_bi, check_qsbc_2nd
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from vnpy.component.chanlun import ChanGraph, ChanLibrary
|
from vnpy.component.chanlun import ChanGraph, ChanLibrary
|
||||||
@ -206,6 +207,8 @@ class CtaLineBar(object):
|
|||||||
self.export_bi_filename = None # 通过缠论笔csv文件
|
self.export_bi_filename = None # 通过缠论笔csv文件
|
||||||
self.export_zs_filename = None # 通过缠论的笔中枢csv文件
|
self.export_zs_filename = None # 通过缠论的笔中枢csv文件
|
||||||
self.export_duan_filename = None # 通过缠论的线段csv文件
|
self.export_duan_filename = None # 通过缠论的线段csv文件
|
||||||
|
self.export_xt_filename = None # 缠论笔的形态csv文件, 满足 strategy_name_xt_n_signals.csv
|
||||||
|
# n 会转换为 3,5,7,9,11,13
|
||||||
|
|
||||||
self.pre_bi_start = None # 前一个笔的时间
|
self.pre_bi_start = None # 前一个笔的时间
|
||||||
self.pre_zs_start = None # 前一个中枢的时间
|
self.pre_zs_start = None # 前一个中枢的时间
|
||||||
@ -295,6 +298,8 @@ class CtaLineBar(object):
|
|||||||
self.param_list.append('para_ema1_len') # 三条EMA均线
|
self.param_list.append('para_ema1_len') # 三条EMA均线
|
||||||
self.param_list.append('para_ema2_len')
|
self.param_list.append('para_ema2_len')
|
||||||
self.param_list.append('para_ema3_len')
|
self.param_list.append('para_ema3_len')
|
||||||
|
self.param_list.append('para_ema4_len')
|
||||||
|
self.param_list.append('para_ema5_len')
|
||||||
|
|
||||||
self.param_list.append('para_dmi_len')
|
self.param_list.append('para_dmi_len')
|
||||||
self.param_list.append('para_dmi_max')
|
self.param_list.append('para_dmi_max')
|
||||||
@ -365,6 +370,7 @@ class CtaLineBar(object):
|
|||||||
self.param_list.append('para_bd_len')
|
self.param_list.append('para_bd_len')
|
||||||
|
|
||||||
self.param_list.append('para_active_chanlun') # 激活缠论
|
self.param_list.append('para_active_chanlun') # 激活缠论
|
||||||
|
self.param_list.append('para_active_chan_xt') # 激活缠论的形态分析
|
||||||
|
|
||||||
def init_properties(self):
|
def init_properties(self):
|
||||||
"""
|
"""
|
||||||
@ -417,6 +423,8 @@ class CtaLineBar(object):
|
|||||||
self.para_ema1_len = 0 # 13 # 第一根EMA均线的周期长度
|
self.para_ema1_len = 0 # 13 # 第一根EMA均线的周期长度
|
||||||
self.para_ema2_len = 0 # 21 # 第二根EMA均线的周期长度
|
self.para_ema2_len = 0 # 21 # 第二根EMA均线的周期长度
|
||||||
self.para_ema3_len = 0 # 120 # 第三根EMA均线的周期长度
|
self.para_ema3_len = 0 # 120 # 第三根EMA均线的周期长度
|
||||||
|
self.para_ema4_len = 0 # 120 # 第四根EMA均线的周期长度
|
||||||
|
self.para_ema5_len = 0 # 120 # 第五根EMA均线的周期长度
|
||||||
|
|
||||||
self.para_dmi_len = 0 # 14 # DMI的计算周期
|
self.para_dmi_len = 0 # 14 # DMI的计算周期
|
||||||
self.para_dmi_max = 0 # 30 # Dpi和Mdi的突破阈值
|
self.para_dmi_max = 0 # 30 # Dpi和Mdi的突破阈值
|
||||||
@ -538,10 +546,14 @@ class CtaLineBar(object):
|
|||||||
self.line_ema1 = [] # K线的EMA1均线,周期是para_ema1_len1,不包含当前bar
|
self.line_ema1 = [] # K线的EMA1均线,周期是para_ema1_len1,不包含当前bar
|
||||||
self.line_ema2 = [] # K线的EMA2均线,周期是para_ema1_len2,不包含当前bar
|
self.line_ema2 = [] # K线的EMA2均线,周期是para_ema1_len2,不包含当前bar
|
||||||
self.line_ema3 = [] # K线的EMA3均线,周期是para_ema1_len3,不包含当前bar
|
self.line_ema3 = [] # K线的EMA3均线,周期是para_ema1_len3,不包含当前bar
|
||||||
|
self.line_ema4 = [] # K线的EMA4均线,周期是para_ema1_len4,不包含当前bar
|
||||||
|
self.line_ema5 = [] # K线的EMA5均线,周期是para_ema1_len5,不包含当前bar
|
||||||
|
|
||||||
self._rt_ema1 = None # K线的实时EMA(para_ema1_len)
|
self._rt_ema1 = None # K线的实时EMA(para_ema1_len)
|
||||||
self._rt_ema2 = None # K线的实时EMA(para_ema2_len)
|
self._rt_ema2 = None # K线的实时EMA(para_ema2_len)
|
||||||
self._rt_ema3 = None # K线的实时EMA(para_ema3_len)
|
self._rt_ema3 = None # K线的实时EMA(para_ema3_len)
|
||||||
|
self._rt_ema4 = None # K线的实时EMA(para_ema4_len)
|
||||||
|
self._rt_ema5 = None # K线的实时EMA(para_ema5_len)
|
||||||
|
|
||||||
# K线的DMI( Pdi,Mdi,ADX,Adxr) 计算数据
|
# K线的DMI( Pdi,Mdi,ADX,Adxr) 计算数据
|
||||||
self.cur_pdi = 0 # bar内的升动向指标,即做多的比率
|
self.cur_pdi = 0 # bar内的升动向指标,即做多的比率
|
||||||
@ -793,6 +805,14 @@ class CtaLineBar(object):
|
|||||||
self._bi_zs_list = [] # 笔中枢列表
|
self._bi_zs_list = [] # 笔中枢列表
|
||||||
self._duan_list = [] # 段列表
|
self._duan_list = [] # 段列表
|
||||||
self._duan_zs_list = [] # 段中枢列表
|
self._duan_zs_list = [] # 段中枢列表
|
||||||
|
self.para_active_chan_xt = False # 是否激活czsc缠论形态识别
|
||||||
|
self.xt_3_signals = [] # czsc 三笔信号列表 {'bi_start'最后一笔开始,'bi_end'最后一笔结束,'signal'}
|
||||||
|
self.xt_5_signals = [] # czsc 五笔信号列表 {'bi_start'最后一笔开始,'bi_end'最后一笔结束,'signal'}
|
||||||
|
self.xt_7_signals = [] # czsc 七笔信号列表 {'bi_start'最后一笔开始,'bi_end'最后一笔结束,'signal'}
|
||||||
|
self.xt_9_signals = [] # czsc 九笔信号列表 {'bi_start'最后一笔开始,'bi_end'最后一笔结束,'signal'}
|
||||||
|
self.xt_11_signals = [] # czsc 11笔信号列表 {'bi_start'最后一笔开始,'bi_end'最后一笔结束,'signal'}
|
||||||
|
self.xt_13_signals = [] # czsc 13笔信号列表 {'bi_start'最后一笔开始,'bi_end'最后一笔结束,'signal'}
|
||||||
|
self.xt_2nd_signals = [] # 趋势背驰2买或趋势背驰2卖信号
|
||||||
|
|
||||||
def set_params(self, setting: dict = {}):
|
def set_params(self, setting: dict = {}):
|
||||||
"""设置参数"""
|
"""设置参数"""
|
||||||
@ -828,7 +848,7 @@ class CtaLineBar(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self.cur_datetime = tick.datetime
|
self.cur_datetime = tick.datetime
|
||||||
self.cur_tick = copy.copy(tick)
|
self.cur_tick = tick #copy.copy(tick)
|
||||||
|
|
||||||
# 兼容 标准套利合约,它没有last_price
|
# 兼容 标准套利合约,它没有last_price
|
||||||
if self.cur_tick.last_price is None or self.cur_tick.last_price == 0:
|
if self.cur_tick.last_price is None or self.cur_tick.last_price == 0:
|
||||||
@ -842,7 +862,7 @@ class CtaLineBar(object):
|
|||||||
self.cur_price = self.cur_tick.last_price
|
self.cur_price = self.cur_tick.last_price
|
||||||
|
|
||||||
# 3.生成x K线,若形成新Bar,则触发OnBar事件
|
# 3.生成x K线,若形成新Bar,则触发OnBar事件
|
||||||
self.generate_bar(copy.copy(self.cur_tick))
|
self.generate_bar(self.cur_tick) # copy.copy(self.cur_tick)
|
||||||
|
|
||||||
# 更新curPeriod的High,low
|
# 更新curPeriod的High,low
|
||||||
if self.cur_period is not None:
|
if self.cur_period is not None:
|
||||||
@ -864,8 +884,8 @@ class CtaLineBar(object):
|
|||||||
self.cur_datetime = bar.datetime + timedelta(minutes=bar_freq)
|
self.cur_datetime = bar.datetime + timedelta(minutes=bar_freq)
|
||||||
|
|
||||||
if self.bar_len == 0:
|
if self.bar_len == 0:
|
||||||
new_bar = copy.deepcopy(bar)
|
#new_bar = copy.deepcopy(bar)
|
||||||
self.line_bar.append(new_bar)
|
self.line_bar.append(bar)
|
||||||
self.cur_trading_day = bar.trading_day
|
self.cur_trading_day = bar.trading_day
|
||||||
self.on_bar(bar)
|
self.on_bar(bar)
|
||||||
return
|
return
|
||||||
@ -910,8 +930,8 @@ class CtaLineBar(object):
|
|||||||
|
|
||||||
if is_new_bar:
|
if is_new_bar:
|
||||||
# 添加新的bar
|
# 添加新的bar
|
||||||
new_bar = copy.deepcopy(bar)
|
#new_bar = copy.deepcopy(bar)
|
||||||
self.line_bar.append(new_bar)
|
self.line_bar.append(bar) # new_bar
|
||||||
# 将上一个Bar推送至OnBar事件
|
# 将上一个Bar推送至OnBar事件
|
||||||
self.on_bar(lastBar)
|
self.on_bar(lastBar)
|
||||||
|
|
||||||
@ -1008,6 +1028,9 @@ class CtaLineBar(object):
|
|||||||
# 输出缠论=》csv文件
|
# 输出缠论=》csv文件
|
||||||
self.export_chan()
|
self.export_chan()
|
||||||
|
|
||||||
|
# 识别缠论分笔形态
|
||||||
|
self.update_chan_xt()
|
||||||
|
|
||||||
# 回调上层调用者,将合成的 x分钟bar,回调给策略 def on_bar_x(self, bar: BarData):函数
|
# 回调上层调用者,将合成的 x分钟bar,回调给策略 def on_bar_x(self, bar: BarData):函数
|
||||||
if self.cb_on_bar:
|
if self.cb_on_bar:
|
||||||
self.cb_on_bar(bar=bar)
|
self.cb_on_bar(bar=bar)
|
||||||
@ -1121,6 +1144,12 @@ class CtaLineBar(object):
|
|||||||
if self.para_ema3_len > 0 and len(self.line_ema3) > 0:
|
if self.para_ema3_len > 0 and len(self.line_ema3) > 0:
|
||||||
msg = msg + u',EMA({0}):{1}'.format(self.para_ema3_len, self.line_ema3[-1])
|
msg = msg + u',EMA({0}):{1}'.format(self.para_ema3_len, self.line_ema3[-1])
|
||||||
|
|
||||||
|
if self.para_ema4_len > 0 and len(self.line_ema4) > 0:
|
||||||
|
msg = msg + u',EMA({0}):{1}'.format(self.para_ema4_len, self.line_ema4[-1])
|
||||||
|
|
||||||
|
if self.para_ema5_len > 0 and len(self.line_ema5) > 0:
|
||||||
|
msg = msg + u',EMA({0}):{1}'.format(self.para_ema5_len, self.line_ema5[-1])
|
||||||
|
|
||||||
if self.para_dmi_len > 0 and len(self.line_pdi) > 0:
|
if self.para_dmi_len > 0 and len(self.line_pdi) > 0:
|
||||||
msg = msg + u',Pdi:{1};Mdi:{1};Adx:{2}'.format(self.line_pdi[-1], self.line_mdi[-1], self.line_adx[-1])
|
msg = msg + u',Pdi:{1};Mdi:{1};Adx:{2}'.format(self.line_pdi[-1], self.line_mdi[-1], self.line_adx[-1])
|
||||||
|
|
||||||
@ -2506,13 +2535,16 @@ class CtaLineBar(object):
|
|||||||
def __count_ema(self):
|
def __count_ema(self):
|
||||||
"""计算K线的EMA1 和EMA2"""
|
"""计算K线的EMA1 和EMA2"""
|
||||||
|
|
||||||
if not (self.para_ema1_len > 0 or self.para_ema2_len > 0 or self.para_ema3_len > 0): # 不计算
|
if not (self.para_ema1_len > 0 or self.para_ema2_len > 0 or self.para_ema3_len > 0
|
||||||
|
or self.para_ema4_len > 0 or self.para_ema5_len > 0): # 不计算
|
||||||
return
|
return
|
||||||
|
|
||||||
ema1_data_len = min(self.para_ema1_len * 4, self.para_ema1_len + 40) if self.para_ema1_len > 0 else 0
|
ema1_data_len = min(self.para_ema1_len * 4, self.para_ema1_len + 40) if self.para_ema1_len > 0 else 0
|
||||||
ema2_data_len = min(self.para_ema2_len * 4, self.para_ema2_len + 40) if self.para_ema2_len > 0 else 0
|
ema2_data_len = min(self.para_ema2_len * 4, self.para_ema2_len + 40) if self.para_ema2_len > 0 else 0
|
||||||
ema3_data_len = min(self.para_ema3_len * 4, self.para_ema3_len + 40) if self.para_ema3_len > 0 else 0
|
ema3_data_len = min(self.para_ema3_len * 4, self.para_ema3_len + 40) if self.para_ema3_len > 0 else 0
|
||||||
max_data_len = max(ema1_data_len, ema2_data_len, ema3_data_len)
|
ema4_data_len = min(self.para_ema4_len * 4, self.para_ema4_len + 40) if self.para_ema4_len > 0 else 0
|
||||||
|
ema5_data_len = min(self.para_ema5_len * 4, self.para_ema5_len + 40) if self.para_ema5_len > 0 else 0
|
||||||
|
max_data_len = max(ema1_data_len, ema2_data_len, ema3_data_len, ema4_data_len, ema5_data_len)
|
||||||
# 1、lineBar满足长度才执行计算
|
# 1、lineBar满足长度才执行计算
|
||||||
if self.bar_len < max_data_len:
|
if self.bar_len < max_data_len:
|
||||||
self.write_log(u'数据未充分,当前Bar数据数量:{0},计算EMA需要:{1}'.
|
self.write_log(u'数据未充分,当前Bar数据数量:{0},计算EMA需要:{1}'.
|
||||||
@ -2524,7 +2556,7 @@ class CtaLineBar(object):
|
|||||||
count_len = min(self.para_ema1_len, self.bar_len - 1)
|
count_len = min(self.para_ema1_len, self.bar_len - 1)
|
||||||
|
|
||||||
# 3、获取前InputN周期(不包含当前周期)的K线
|
# 3、获取前InputN周期(不包含当前周期)的K线
|
||||||
barEma1 = ta.EMA(self.close_array[-ema1_data_len:], count_len)[-1]
|
barEma1 = ta.EMA(self.close_array[-self.para_ema1_len * 4:], count_len)[-1]
|
||||||
if np.isnan(barEma1):
|
if np.isnan(barEma1):
|
||||||
return
|
return
|
||||||
barEma1 = round(float(barEma1), self.round_n)
|
barEma1 = round(float(barEma1), self.round_n)
|
||||||
@ -2539,7 +2571,7 @@ class CtaLineBar(object):
|
|||||||
|
|
||||||
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
||||||
|
|
||||||
barEma2 = ta.EMA(self.close_array[-ema2_data_len:], count_len)[-1]
|
barEma2 = ta.EMA(self.close_array[-self.para_ema2_len * 4:], count_len)[-1]
|
||||||
if np.isnan(barEma2):
|
if np.isnan(barEma2):
|
||||||
return
|
return
|
||||||
barEma2 = round(float(barEma2), self.round_n)
|
barEma2 = round(float(barEma2), self.round_n)
|
||||||
@ -2553,7 +2585,7 @@ class CtaLineBar(object):
|
|||||||
count_len = min(self.bar_len - 1, self.para_ema3_len)
|
count_len = min(self.bar_len - 1, self.para_ema3_len)
|
||||||
|
|
||||||
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
||||||
barEma3 = ta.EMA(self.close_array[-ema3_data_len:], count_len)[-1]
|
barEma3 = ta.EMA(self.close_array[-self.para_ema3_len * 4:], count_len)[-1]
|
||||||
if np.isnan(barEma3):
|
if np.isnan(barEma3):
|
||||||
return
|
return
|
||||||
barEma3 = round(float(barEma3), self.round_n)
|
barEma3 = round(float(barEma3), self.round_n)
|
||||||
@ -2562,16 +2594,47 @@ class CtaLineBar(object):
|
|||||||
del self.line_ema3[0]
|
del self.line_ema3[0]
|
||||||
self.line_ema3.append(barEma3)
|
self.line_ema3.append(barEma3)
|
||||||
|
|
||||||
|
# 计算第四条EMA均线
|
||||||
|
if self.para_ema4_len > 0:
|
||||||
|
count_len = min(self.bar_len - 1, self.para_ema4_len)
|
||||||
|
|
||||||
|
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
||||||
|
barEma4 = ta.EMA(self.close_array[-self.para_ema4_len * 4:], count_len)[-1]
|
||||||
|
if np.isnan(barEma4):
|
||||||
|
return
|
||||||
|
barEma4 = round(float(barEma4), self.round_n)
|
||||||
|
|
||||||
|
if len(self.line_ema4) > self.max_hold_bars:
|
||||||
|
del self.line_ema4[0]
|
||||||
|
self.line_ema4.append(barEma4)
|
||||||
|
|
||||||
|
# 计算第五条EMA均线
|
||||||
|
if self.para_ema5_len > 0:
|
||||||
|
count_len = min(self.bar_len - 1, self.para_ema5_len)
|
||||||
|
|
||||||
|
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
||||||
|
barEma5 = ta.EMA(self.close_array[-self.para_ema5_len * 4:], count_len)[-1]
|
||||||
|
if np.isnan(barEma5):
|
||||||
|
return
|
||||||
|
barEma5 = round(float(barEma5), self.round_n)
|
||||||
|
|
||||||
|
if len(self.line_ema5) > self.max_hold_bars:
|
||||||
|
del self.line_ema5[0]
|
||||||
|
self.line_ema5.append(barEma5)
|
||||||
|
|
||||||
def rt_count_ema(self):
|
def rt_count_ema(self):
|
||||||
"""计算K线的EMA1 和EMA2"""
|
"""计算K线的EMA1 和EMA2"""
|
||||||
|
|
||||||
if not (self.para_ema1_len > 0 or self.para_ema2_len > 0 or self.para_ema3_len > 0): # 不计算
|
if not (self.para_ema1_len > 0 or self.para_ema2_len > 0 or self.para_ema3_len > 0
|
||||||
|
or self.para_ema4_len > 0 or self.para_ema5_len > 0): # 不计算
|
||||||
return
|
return
|
||||||
|
|
||||||
ema1_data_len = min(self.para_ema1_len * 4, self.para_ema1_len + 40) if self.para_ema1_len > 0 else 0
|
ema1_data_len = min(self.para_ema1_len * 4, self.para_ema1_len + 40) if self.para_ema1_len > 0 else 0
|
||||||
ema2_data_len = min(self.para_ema2_len * 4, self.para_ema2_len + 40) if self.para_ema2_len > 0 else 0
|
ema2_data_len = min(self.para_ema2_len * 4, self.para_ema2_len + 40) if self.para_ema2_len > 0 else 0
|
||||||
ema3_data_len = min(self.para_ema3_len * 4, self.para_ema3_len + 40) if self.para_ema3_len > 0 else 0
|
ema3_data_len = min(self.para_ema3_len * 4, self.para_ema3_len + 40) if self.para_ema3_len > 0 else 0
|
||||||
max_data_len = max(ema1_data_len, ema2_data_len, ema3_data_len)
|
ema4_data_len = min(self.para_ema4_len * 4, self.para_ema4_len + 40) if self.para_ema4_len > 0 else 0
|
||||||
|
ema5_data_len = min(self.para_ema5_len * 4, self.para_ema5_len + 40) if self.para_ema5_len > 0 else 0
|
||||||
|
max_data_len = max(ema1_data_len, ema2_data_len, ema3_data_len, ema4_data_len, ema5_data_len)
|
||||||
# 1、lineBar满足长度才执行计算
|
# 1、lineBar满足长度才执行计算
|
||||||
if self.bar_len < max_data_len:
|
if self.bar_len < max_data_len:
|
||||||
return
|
return
|
||||||
@ -2581,7 +2644,7 @@ class CtaLineBar(object):
|
|||||||
count_len = min(self.para_ema1_len, self.bar_len)
|
count_len = min(self.para_ema1_len, self.bar_len)
|
||||||
|
|
||||||
# 3、获取前InputN周期(不包含当前周期)的K线
|
# 3、获取前InputN周期(不包含当前周期)的K线
|
||||||
barEma1 = ta.EMA(np.append(self.close_array[-ema1_data_len:], [self.cur_price]), count_len)[-1]
|
barEma1 = ta.EMA(np.append(self.close_array[-self.para_ema1_len * 4:], [self.cur_price]), count_len)[-1]
|
||||||
if np.isnan(barEma1):
|
if np.isnan(barEma1):
|
||||||
return
|
return
|
||||||
self._rt_ema1 = round(float(barEma1), self.round_n)
|
self._rt_ema1 = round(float(barEma1), self.round_n)
|
||||||
@ -2592,7 +2655,7 @@ class CtaLineBar(object):
|
|||||||
|
|
||||||
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
||||||
|
|
||||||
barEma2 = ta.EMA(np.append(self.close_array[-ema2_data_len:], [self.cur_price]), count_len)[-1]
|
barEma2 = ta.EMA(np.append(self.close_array[-self.para_ema2_len * 4:], [self.cur_price]), count_len)[-1]
|
||||||
if np.isnan(barEma2):
|
if np.isnan(barEma2):
|
||||||
return
|
return
|
||||||
self._rt_ema2 = round(float(barEma2), self.round_n)
|
self._rt_ema2 = round(float(barEma2), self.round_n)
|
||||||
@ -2602,11 +2665,31 @@ class CtaLineBar(object):
|
|||||||
count_len = min(self.bar_len, self.para_ema3_len)
|
count_len = min(self.bar_len, self.para_ema3_len)
|
||||||
|
|
||||||
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
||||||
barEma3 = ta.EMA(np.append(self.close_array[-ema3_data_len:], [self.cur_price]), count_len)[-1]
|
barEma3 = ta.EMA(np.append(self.close_array[-self.para_ema3_len * 4:], [self.cur_price]), count_len)[-1]
|
||||||
if np.isnan(barEma3):
|
if np.isnan(barEma3):
|
||||||
return
|
return
|
||||||
self._rt_ema3 = round(float(barEma3), self.round_n)
|
self._rt_ema3 = round(float(barEma3), self.round_n)
|
||||||
|
|
||||||
|
# 计算第四条EMA均线
|
||||||
|
if self.para_ema4_len > 0:
|
||||||
|
count_len = min(self.bar_len, self.para_ema4_len)
|
||||||
|
|
||||||
|
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
||||||
|
barEma4 = ta.EMA(np.append(self.close_array[-self.para_ema4_len * 4:], [self.cur_price]), count_len)[-1]
|
||||||
|
if np.isnan(barEma4):
|
||||||
|
return
|
||||||
|
self._rt_ema4 = round(float(barEma4), self.round_n)
|
||||||
|
|
||||||
|
# 计算第五条EMA均线
|
||||||
|
if self.para_ema5_len > 0:
|
||||||
|
count_len = min(self.bar_len, self.para_ema5_len)
|
||||||
|
|
||||||
|
# 3、获取前InputN周期(不包含当前周期)的自适应均线
|
||||||
|
barEma5 = ta.EMA(np.append(self.close_array[-self.para_ema5_len * 4:], [self.cur_price]), count_len)[-1]
|
||||||
|
if np.isnan(barEma5):
|
||||||
|
return
|
||||||
|
self._rt_ema5 = round(float(barEma5), self.round_n)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rt_ema1(self):
|
def rt_ema1(self):
|
||||||
self.check_rt_funcs(self.rt_count_ema)
|
self.check_rt_funcs(self.rt_count_ema)
|
||||||
@ -2628,6 +2711,20 @@ class CtaLineBar(object):
|
|||||||
return self.line_ema3[-1]
|
return self.line_ema3[-1]
|
||||||
return self._rt_ema3
|
return self._rt_ema3
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rt_ema4(self):
|
||||||
|
self.check_rt_funcs(self.rt_count_ema)
|
||||||
|
if self._rt_ema4 is None and len(self.line_ema4) > 0:
|
||||||
|
return self.line_ema4[-1]
|
||||||
|
return self._rt_ema4
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rt_ema5(self):
|
||||||
|
self.check_rt_funcs(self.rt_count_ema)
|
||||||
|
if self._rt_ema5 is None and len(self.line_ema5) > 0:
|
||||||
|
return self.line_ema5[-1]
|
||||||
|
return self._rt_ema5
|
||||||
|
|
||||||
def __count_dmi(self):
|
def __count_dmi(self):
|
||||||
"""计算K线的DMI数据和条件"""
|
"""计算K线的DMI数据和条件"""
|
||||||
|
|
||||||
@ -5806,7 +5903,7 @@ class CtaLineBar(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# 当前段包含的分笔,必须大于3
|
# 当前段包含的分笔,必须大于3
|
||||||
if len(cur_duan.bi_list) < 3:
|
if len(cur_duan.bi_list) <= 3:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 获取倒数第二根同向分笔的结束dif值或macd值
|
# 获取倒数第二根同向分笔的结束dif值或macd值
|
||||||
@ -6132,6 +6229,79 @@ class CtaLineBar(object):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def update_chan_xt(self):
|
||||||
|
"""更新缠论形态"""
|
||||||
|
if not self.para_active_chan_xt:
|
||||||
|
return
|
||||||
|
bi_len = len(self.bi_list)
|
||||||
|
if bi_len < 3:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.cur_fenxing.is_rt:
|
||||||
|
return
|
||||||
|
|
||||||
|
bi_n = min(15, bi_len)
|
||||||
|
|
||||||
|
price = self.cur_bi.low if self.cur_bi.direction == -1 else self.cur_bi.high
|
||||||
|
|
||||||
|
for n in range(3, bi_n, 2):
|
||||||
|
# => 信号
|
||||||
|
if n == 3:
|
||||||
|
signal = check_chan_xt_three_bi(self, self.bi_list[-n:])
|
||||||
|
else:
|
||||||
|
signal = check_chan_xt(self, self.bi_list[-n:])
|
||||||
|
# => 信号列表
|
||||||
|
xt_signals = getattr(self, f'xt_{n}_signals')
|
||||||
|
if xt_signals is None:
|
||||||
|
continue
|
||||||
|
# => 上一信号
|
||||||
|
cur_signal = xt_signals[-1] if len(xt_signals) > 0 else None
|
||||||
|
# 不同笔开始时间
|
||||||
|
if cur_signal is None or cur_signal.get("start", "") != self.cur_bi.start:
|
||||||
|
# 新增
|
||||||
|
xt_signals.append({'start': self.cur_bi.start,
|
||||||
|
'end': self.cur_bi.end,
|
||||||
|
'price': price,
|
||||||
|
'signal': signal})
|
||||||
|
if len(xt_signals) > 200:
|
||||||
|
del xt_signals[0]
|
||||||
|
if cur_signal is not None and self.export_xt_filename :
|
||||||
|
self.append_data(
|
||||||
|
file_name=self.export_xt_filename.replace('_n_',f'_{n}_'),
|
||||||
|
dict_data=cur_signal,
|
||||||
|
field_names=["start", "end", "price", "signal"]
|
||||||
|
)
|
||||||
|
# 直接更新
|
||||||
|
else:
|
||||||
|
xt_signals[-1].update({'end': self.cur_bi.end, 'price': price,'signal': signal})
|
||||||
|
|
||||||
|
# 是否趋势二买
|
||||||
|
qsbc_2nd = ChanSignals.Other.value
|
||||||
|
if self.cur_bi.direction == -1:
|
||||||
|
if check_qsbc_2nd(big_kline=self, small_kline=None, signal_direction=Direction.LONG):
|
||||||
|
qsbc_2nd = ChanSignals.Q2L0.value
|
||||||
|
else:
|
||||||
|
if check_qsbc_2nd(big_kline=self, small_kline=None,signal_direction=Direction.SHORT):
|
||||||
|
qsbc_2nd = ChanSignals.Q2S0.value
|
||||||
|
cur_signal = self.xt_2nd_signals[-1] if len(self.xt_2nd_signals) > 0 else None
|
||||||
|
# 不同笔开始时间
|
||||||
|
if cur_signal is None or cur_signal.get("start", "") != self.cur_bi.start:
|
||||||
|
# 新增
|
||||||
|
self.xt_2nd_signals.append({'start': self.cur_bi.start,
|
||||||
|
'end': self.cur_bi.end,
|
||||||
|
'price': price,
|
||||||
|
'signal': qsbc_2nd})
|
||||||
|
if cur_signal and self.export_xt_filename:
|
||||||
|
self.append_data(
|
||||||
|
file_name=self.export_xt_filename.replace('_n_', f'_2nd_'),
|
||||||
|
dict_data=cur_signal,
|
||||||
|
field_names=["start", "end", "price", "signal"]
|
||||||
|
)
|
||||||
|
# 直接更新
|
||||||
|
else:
|
||||||
|
self.xt_2nd_signals[-1].update({'end': self.cur_bi.end, 'price': price, 'signal': qsbc_2nd})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def write_log(self, content):
|
def write_log(self, content):
|
||||||
"""记录CTA日志"""
|
"""记录CTA日志"""
|
||||||
@ -6338,6 +6508,22 @@ class CtaLineBar(object):
|
|||||||
'type': 'line'
|
'type': 'line'
|
||||||
}
|
}
|
||||||
indicators.update({indicator.get('name'): copy.copy(indicator)})
|
indicators.update({indicator.get('name'): copy.copy(indicator)})
|
||||||
|
if isinstance(self.para_ema4_len, int) and self.para_ema4_len > 0:
|
||||||
|
indicator = {
|
||||||
|
'name': 'EMA{}'.format(self.para_ema4_len),
|
||||||
|
'attr_name': 'line_ema4',
|
||||||
|
'is_main': True,
|
||||||
|
'type': 'line'
|
||||||
|
}
|
||||||
|
indicators.update({indicator.get('name'): copy.copy(indicator)})
|
||||||
|
if isinstance(self.para_ema5_len, int) and self.para_ema5_len > 0:
|
||||||
|
indicator = {
|
||||||
|
'name': 'EMA{}'.format(self.para_ema5_len),
|
||||||
|
'attr_name': 'line_ema5',
|
||||||
|
'is_main': True,
|
||||||
|
'type': 'line'
|
||||||
|
}
|
||||||
|
indicators.update({indicator.get('name'): copy.copy(indicator)})
|
||||||
|
|
||||||
# MA 均线 (主图)
|
# MA 均线 (主图)
|
||||||
if isinstance(self.para_ma1_len, int) and self.para_ma1_len > 0:
|
if isinstance(self.para_ma1_len, int) and self.para_ma1_len > 0:
|
||||||
@ -6820,9 +7006,9 @@ class CtaMinuteBar(CtaLineBar):
|
|||||||
is_new_bar = True
|
is_new_bar = True
|
||||||
|
|
||||||
if is_new_bar:
|
if is_new_bar:
|
||||||
new_bar = copy.deepcopy(bar)
|
#new_bar = copy.deepcopy(bar)
|
||||||
# 添加新的bar
|
# 添加新的bar
|
||||||
self.line_bar.append(new_bar)
|
self.line_bar.append(bar) # new_bar
|
||||||
# 将上一个Bar推送至OnBar事件
|
# 将上一个Bar推送至OnBar事件
|
||||||
self.on_bar(lastBar)
|
self.on_bar(lastBar)
|
||||||
else:
|
else:
|
||||||
@ -7261,8 +7447,8 @@ class CtaDayBar(CtaLineBar):
|
|||||||
bar_len = len(self.line_bar)
|
bar_len = len(self.line_bar)
|
||||||
|
|
||||||
if bar_len == 0:
|
if bar_len == 0:
|
||||||
new_bar = copy.deepcopy(bar)
|
#new_bar = copy.deepcopy(bar)
|
||||||
self.line_bar.append(new_bar)
|
self.line_bar.append(bar) # new_bar
|
||||||
self.cur_trading_day = bar.trading_day if bar.trading_day is not None else get_trading_date(bar.datetime)
|
self.cur_trading_day = bar.trading_day if bar.trading_day is not None else get_trading_date(bar.datetime)
|
||||||
if bar_is_completed:
|
if bar_is_completed:
|
||||||
self.on_bar(bar)
|
self.on_bar(bar)
|
||||||
@ -7288,8 +7474,8 @@ class CtaDayBar(CtaLineBar):
|
|||||||
|
|
||||||
if is_new_bar:
|
if is_new_bar:
|
||||||
# 添加新的bar
|
# 添加新的bar
|
||||||
new_bar = copy.deepcopy(bar)
|
#new_bar = copy.deepcopy(bar)
|
||||||
self.line_bar.append(new_bar)
|
self.line_bar.append(bar) # new_bar
|
||||||
# 将上一个Bar推送至OnBar事件
|
# 将上一个Bar推送至OnBar事件
|
||||||
self.on_bar(lastBar)
|
self.on_bar(lastBar)
|
||||||
else:
|
else:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
# 周期类,定义CTA的五种周期,及其周期变换矩阵
|
# 周期状态类,定义CTA的多种周期状态,及其状态变换矩阵
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
@ -9,8 +9,12 @@ from datetime import datetime
|
|||||||
class Period(Enum):
|
class Period(Enum):
|
||||||
INIT = u'初始状态'
|
INIT = u'初始状态'
|
||||||
LONG = u'多'
|
LONG = u'多'
|
||||||
|
LONG_STOP = u'止涨'
|
||||||
SHORT = u'空'
|
SHORT = u'空'
|
||||||
|
SHORT_STOP = u'止跌'
|
||||||
SHOCK = u'震荡'
|
SHOCK = u'震荡'
|
||||||
|
SHOCK_LONG = u'震荡偏多'
|
||||||
|
SHOCK_SHORT = u'震荡偏空'
|
||||||
LONG_EXTREME = u'极端多'
|
LONG_EXTREME = u'极端多'
|
||||||
SHORT_EXTREME = u'极端空'
|
SHORT_EXTREME = u'极端空'
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from vnpy.component.base import CtaComponent
|
from vnpy.component.base import CtaComponent, MyEncoder
|
||||||
from vnpy.trader.utility import get_folder_path
|
from vnpy.trader.utility import get_folder_path
|
||||||
|
|
||||||
TNS_STATUS_OBSERVATE = 'observate'
|
TNS_STATUS_OBSERVATE = 'observate'
|
||||||
@ -15,24 +15,6 @@ TNS_STATUS_CLOSED = 'closed'
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class MyEncoder(json.JSONEncoder):
|
|
||||||
"""
|
|
||||||
自定义转换器,处理np,datetime等不能被json转换得问题
|
|
||||||
"""
|
|
||||||
def default(self, obj):
|
|
||||||
if isinstance(obj, np.integer):
|
|
||||||
return int(obj)
|
|
||||||
elif isinstance(obj, np.floating):
|
|
||||||
return float(obj)
|
|
||||||
elif isinstance(obj, np.ndarray):
|
|
||||||
return obj.tolist()
|
|
||||||
elif isinstance(obj, datetime):
|
|
||||||
return obj.strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
else:
|
|
||||||
return super(MyEncoder, self).default(obj)
|
|
||||||
|
|
||||||
|
|
||||||
class CtaPolicy(CtaComponent):
|
class CtaPolicy(CtaComponent):
|
||||||
"""
|
"""
|
||||||
策略的持久化Policy组件
|
策略的持久化Policy组件
|
||||||
|
@ -4,15 +4,16 @@
|
|||||||
|
|
||||||
from vnpy.trader.constant import ChanSignals, Direction
|
from vnpy.trader.constant import ChanSignals, Direction
|
||||||
from vnpy.component.chanlun.pyChanlun import ChanBi, ChanDuan, ChanObject
|
from vnpy.component.chanlun.pyChanlun import ChanBi, ChanDuan, ChanObject
|
||||||
from vnpy.component.cta_line_bar import CtaLineBar
|
# from vnpy.component.cta_line_bar import CtaLineBar
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
|
|
||||||
# 所有底背驰信号集合
|
# 所有底背驰信号集合
|
||||||
DI_BEICHI_SIGNALS = [ChanSignals.LA0.value, ChanSignals.LA1.value, ChanSignals.LA2.value, ChanSignals.LA3.value,
|
DI_BEICHI_SIGNALS = [ChanSignals.LA0.value,
|
||||||
ChanSignals.LB0.value, ChanSignals.LB1.value, ChanSignals.LB2.value, ChanSignals.LB3.value]
|
ChanSignals.LB0.value]
|
||||||
|
|
||||||
# 所有顶背驰信号集合
|
# 所有顶背驰信号集合
|
||||||
DING_BEICHI_SIGNALS = [ChanSignals.SA0.value, ChanSignals.SA1.value, ChanSignals.SA2.value, ChanSignals.SA3.value,
|
DING_BEICHI_SIGNALS = [ChanSignals.SA0.value,
|
||||||
ChanSignals.SB0.value, ChanSignals.SB1.value, ChanSignals.SB2.value, ChanSignals.SB3.value]
|
ChanSignals.SB0.value]
|
||||||
|
|
||||||
|
|
||||||
def duan_bi_is_end(duan: ChanDuan, direction: Direction) -> bool:
|
def duan_bi_is_end(duan: ChanDuan, direction: Direction) -> bool:
|
||||||
@ -37,7 +38,7 @@ def duan_bi_is_end(duan: ChanDuan, direction: Direction) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_duan_not_rt(kline: CtaLineBar, direction: Direction) -> bool:
|
def check_duan_not_rt(kline, direction: Direction) -> bool:
|
||||||
"""
|
"""
|
||||||
检查某一个K线当前线段是否非实时
|
检查某一个K线当前线段是否非实时
|
||||||
:param kline:
|
:param kline:
|
||||||
@ -58,7 +59,7 @@ def check_duan_not_rt(kline: CtaLineBar, direction: Direction) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def check_bi_not_rt(kline: CtaLineBar, direction: Direction) -> bool:
|
def check_bi_not_rt(kline, direction: Direction) -> bool:
|
||||||
"""
|
"""
|
||||||
检查某一个K线当前分笔是否非实时并符合判断方向
|
检查某一个K线当前分笔是否非实时并符合判断方向
|
||||||
:param kline:
|
:param kline:
|
||||||
@ -84,7 +85,7 @@ def check_bi_not_rt(kline: CtaLineBar, direction: Direction) -> bool:
|
|||||||
# 判断还没走完的bar,是否满足顶分型
|
# 判断还没走完的bar,是否满足顶分型
|
||||||
if float(kline.cur_fenxing.high) == float(kline.high_array[-1]) \
|
if float(kline.cur_fenxing.high) == float(kline.high_array[-1]) \
|
||||||
and kline.cur_fenxing.index == kline.index_list[-1] \
|
and kline.cur_fenxing.index == kline.index_list[-1] \
|
||||||
and kline.line_bar[-1].datetime.strftime('%Y-%m-%d %H:%M:%S') > kline.cur_fenxing.index\
|
and kline.line_bar[-1].datetime.strftime('%Y-%m-%d %H:%M:%S') > kline.cur_fenxing.index \
|
||||||
and kline.line_bar[-1].high_price < float(kline.cur_fenxing.high) \
|
and kline.line_bar[-1].high_price < float(kline.cur_fenxing.high) \
|
||||||
and kline.line_bar[-1].low_price < kline.line_bar[-2].low_price:
|
and kline.line_bar[-1].low_price < kline.line_bar[-2].low_price:
|
||||||
return True
|
return True
|
||||||
@ -103,7 +104,7 @@ def check_bi_not_rt(kline: CtaLineBar, direction: Direction) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def check_fx_power(kline: CtaLineBar, direction: Direction) -> str:
|
def check_fx_power(kline, direction: Direction) -> str:
|
||||||
"""
|
"""
|
||||||
获取分型强弱
|
获取分型强弱
|
||||||
:param kline: 本级别K线
|
:param kline: 本级别K线
|
||||||
@ -165,7 +166,7 @@ def check_fx_power(kline: CtaLineBar, direction: Direction) -> str:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def check_chan_xt(kline: CtaLineBar, bi_list: List[ChanObject]) -> str:
|
def check_chan_xt(kline, bi_list: List[ChanObject]) -> str:
|
||||||
"""
|
"""
|
||||||
获取缠论得形态
|
获取缠论得形态
|
||||||
如果提供得是段内得bi_list,一般可以算出该线段是否有背驰,
|
如果提供得是段内得bi_list,一般可以算出该线段是否有背驰,
|
||||||
@ -189,12 +190,12 @@ def check_chan_xt(kline: CtaLineBar, bi_list: List[ChanObject]) -> str:
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def check_chan_xt_three_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
def check_chan_xt_three_bi(kline, bi_list: List[ChanObject]):
|
||||||
"""
|
"""
|
||||||
获取指定3分笔得形态
|
获取指定3分笔得形态
|
||||||
(含有三笔)
|
(含有三笔)
|
||||||
:param kline:
|
:param kline: ctaLineBar对象
|
||||||
:param bi_list:
|
:param bi_list: 笔列表
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
v = ChanSignals.Other.value
|
v = ChanSignals.Other.value
|
||||||
@ -207,62 +208,146 @@ def check_chan_xt_three_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
|||||||
# 最后一笔是下跌
|
# 最后一笔是下跌
|
||||||
if bi_3.direction == -1:
|
if bi_3.direction == -1:
|
||||||
# X3LA0~向下不重合
|
# X3LA0~向下不重合
|
||||||
|
# ^
|
||||||
|
# / \
|
||||||
|
# / \
|
||||||
|
# /
|
||||||
|
# \ /
|
||||||
|
# \ /
|
||||||
|
# v
|
||||||
if bi_3.low > bi_1.high:
|
if bi_3.low > bi_1.high:
|
||||||
v = ChanSignals.X3LA0.value
|
v = ChanSignals.X3LA0.value
|
||||||
|
|
||||||
# X3LB0~向下奔走型中枢
|
# X3LB0~向下奔走型
|
||||||
|
# ^
|
||||||
|
# / \
|
||||||
|
# / \
|
||||||
|
# \ / \
|
||||||
|
# \ /
|
||||||
|
# \ /
|
||||||
|
# v
|
||||||
if bi_2.low < bi_3.low < bi_1.high < bi_2.high:
|
if bi_2.low < bi_3.low < bi_1.high < bi_2.high:
|
||||||
v = ChanSignals.X3LB0.value
|
v = ChanSignals.X3LB0.value
|
||||||
|
|
||||||
# X3LC0~向下三角收敛中枢
|
# X3LC0~向下收敛
|
||||||
|
# \
|
||||||
|
# \ ^
|
||||||
|
# \ / \
|
||||||
|
# \ / \
|
||||||
|
# \ /
|
||||||
|
# \ /
|
||||||
|
# v
|
||||||
if bi_1.high > bi_3.high and bi_1.low < bi_3.low:
|
if bi_1.high > bi_3.high and bi_1.low < bi_3.low:
|
||||||
v = ChanSignals.X3LC0.value
|
v = ChanSignals.X3LC0.value
|
||||||
|
|
||||||
# 向下三角扩张中枢
|
# X3LD0~向下扩张
|
||||||
|
# ^
|
||||||
|
# / \
|
||||||
|
# \ / \
|
||||||
|
# \ / \
|
||||||
|
# v \
|
||||||
|
# \
|
||||||
if bi_1.high < bi_3.high and bi_1.low > bi_3.low:
|
if bi_1.high < bi_3.high and bi_1.low > bi_3.low:
|
||||||
v = ChanSignals.X3LD0.value
|
v = ChanSignals.X3LD0.value
|
||||||
|
|
||||||
# X3LE0~向下盘背中枢, X3LF0~向下无背中枢
|
# X3LE0~向下盘背, X3LF0~向下无背
|
||||||
if bi_3.low < bi_1.low and bi_3.high < bi_1.high:
|
if bi_3.low < bi_1.low and bi_3.high < bi_1.high:
|
||||||
if bi_3.height < bi_1.height:
|
if bi_3.height < bi_1.height:
|
||||||
# X3LE0~向下盘背中枢
|
# X3LE0~向下盘背
|
||||||
|
# \
|
||||||
|
# \
|
||||||
|
# \ ^
|
||||||
|
# \ / \
|
||||||
|
# \ / \
|
||||||
|
# v \
|
||||||
|
# \
|
||||||
v = ChanSignals.X3LE0.value
|
v = ChanSignals.X3LE0.value
|
||||||
else:
|
else:
|
||||||
# X3LF0~向下无背中枢
|
# X3LF0~向下无背中枢
|
||||||
|
# \
|
||||||
|
# \ ^
|
||||||
|
# \ / \
|
||||||
|
# \ / \
|
||||||
|
# v \
|
||||||
|
# \
|
||||||
|
# \
|
||||||
v = ChanSignals.X3LF0.value
|
v = ChanSignals.X3LF0.value
|
||||||
|
|
||||||
# 上涨线段
|
# 上涨线段
|
||||||
elif bi_3.direction == 1:
|
elif bi_3.direction == 1:
|
||||||
# X3SA0~向上不重合
|
# X3SA0~向上不重合
|
||||||
if bi_3.high > bi_1.low:
|
# ^
|
||||||
|
# / \
|
||||||
|
# / \
|
||||||
|
# \
|
||||||
|
# \ /
|
||||||
|
# \ /
|
||||||
|
# v
|
||||||
|
if bi_3.high < bi_1.low:
|
||||||
v = ChanSignals.X3SA0.value
|
v = ChanSignals.X3SA0.value
|
||||||
|
|
||||||
# X3SB0~向上奔走型中枢
|
# X3SB0~向上奔走型
|
||||||
|
# ^
|
||||||
|
# / \
|
||||||
|
# / \ /
|
||||||
|
# / \ /
|
||||||
|
# \ /
|
||||||
|
# v
|
||||||
if bi_2.low < bi_1.low < bi_3.high < bi_2.high:
|
if bi_2.low < bi_1.low < bi_3.high < bi_2.high:
|
||||||
v = ChanSignals.X3SB0.value
|
v = ChanSignals.X3SB0.value
|
||||||
|
|
||||||
# X3SC0~向上三角收敛中枢
|
# X3SC0~向上收敛
|
||||||
|
# ^
|
||||||
|
# / \
|
||||||
|
# / \ /
|
||||||
|
# / \ /
|
||||||
|
# / v
|
||||||
|
# /
|
||||||
if bi_1.high > bi_3.high and bi_1.low < bi_3.low:
|
if bi_1.high > bi_3.high and bi_1.low < bi_3.low:
|
||||||
v = ChanSignals.X3SC0.value
|
v = ChanSignals.X3SC0.value
|
||||||
|
|
||||||
# X3SD0~向上三角扩张中枢
|
# X3SD0~向上扩张
|
||||||
|
# /
|
||||||
|
# ^ /
|
||||||
|
# / \ /
|
||||||
|
# / \ /
|
||||||
|
# / \ /
|
||||||
|
# v
|
||||||
if bi_1.high < bi_3.high and bi_1.low > bi_3.low:
|
if bi_1.high < bi_3.high and bi_1.low > bi_3.low:
|
||||||
v = ChanSignals.X3SD0.value
|
v = ChanSignals.X3SD0.value
|
||||||
# X3SE0~向上盘背中枢,X3SF0~向上无背中枢
|
|
||||||
|
# X3SE0~向上盘背,X3SF0~向上无背
|
||||||
if bi_3.low > bi_1.low and bi_3.high > bi_1.high:
|
if bi_3.low > bi_1.low and bi_3.high > bi_1.high:
|
||||||
if bi_3.height < bi_1.height:
|
if bi_3.height < bi_1.height:
|
||||||
# X3SE0~向上盘背中枢
|
# X3SE0~向上盘背
|
||||||
|
# /
|
||||||
|
# ^ /
|
||||||
|
# / \ /
|
||||||
|
# / \ /
|
||||||
|
# / \ /
|
||||||
|
# / v
|
||||||
|
# /
|
||||||
|
# /
|
||||||
v = ChanSignals.X3SE0.value
|
v = ChanSignals.X3SE0.value
|
||||||
else:
|
else:
|
||||||
# X3SF0~向上无背中枢
|
# X3SF0~向上无背
|
||||||
|
# /
|
||||||
|
# /
|
||||||
|
# ^ /
|
||||||
|
# / \ /
|
||||||
|
# / \ /
|
||||||
|
# / \ /
|
||||||
|
# / v
|
||||||
|
# /
|
||||||
v = ChanSignals.X3SF0.value
|
v = ChanSignals.X3SF0.value
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def check_chan_xt_five_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
def check_chan_xt_five_bi(kline, bi_list: List[ChanObject]):
|
||||||
"""识别当前5笔形态
|
"""识别当前5笔形态
|
||||||
:param cur_duan: 当前线段
|
:param kline: ctaLineBar对象
|
||||||
|
:param bi_list: 笔列表
|
||||||
:return: str
|
:return: str
|
||||||
"""
|
"""
|
||||||
v = ChanSignals.Other.value
|
v = ChanSignals.Other.value
|
||||||
@ -282,77 +367,77 @@ def check_chan_xt_five_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
|||||||
# aAb式底背驰
|
# aAb式底背驰
|
||||||
if min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) and max_high == bi_1.high and bi_5.height < bi_1.height:
|
if min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) and max_high == bi_1.high and bi_5.height < bi_1.height:
|
||||||
if (min_low == bi_3.low and bi_5.low < bi_1.low) or (min_low == bi_5.low):
|
if (min_low == bi_3.low and bi_5.low < bi_1.low) or (min_low == bi_5.low):
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.LA0.value # "底背驰”五笔aAb式
|
||||||
|
|
||||||
# 类趋势底背驰( 笔5 的强度比笔1、笔3低)
|
# 类趋势底背驰( 笔5 的强度比笔1、笔3低)
|
||||||
if max_high == bi_1.high and min_low == bi_5.low and bi_4.high < bi_2.low \
|
if max_high == bi_1.high and min_low == bi_5.low and bi_4.high < bi_2.low \
|
||||||
and bi_5.height < max(bi_3.height, bi_1.height) \
|
and bi_5.height < max(bi_3.height, bi_1.height) \
|
||||||
and bi_5.atan < max(bi_3.atan, bi_1.atan):
|
and bi_5.atan < max(bi_3.atan, bi_1.atan):
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.LA0.value # "底背驰" 五笔类趋势
|
||||||
|
|
||||||
# 上颈线突破
|
# 上颈线突破
|
||||||
if (min_low == bi_1.low and bi_5.high > min(bi_1.high, bi_2.high) > bi_5.low > bi_1.low) \
|
if (min_low == bi_1.low and bi_5.high > min(bi_1.high, bi_2.high) > bi_5.low > bi_1.low) \
|
||||||
or (min_low == bi_3.low and bi_5.high > bi_3.high > bi_5.low > bi_3.low):
|
or (min_low == bi_3.low and bi_5.high > bi_3.high > bi_5.low > bi_3.low):
|
||||||
v = ChanSignals.LG0.value
|
return ChanSignals.LG0.value # 上颈线突破 五笔
|
||||||
|
|
||||||
# 五笔三买,要求bi_5.high是最高点, 或者bi_4.height,超过笔2、笔3两倍
|
# 五笔三买,要求bi_5.high是最高点, 或者bi_4.height,超过笔2、笔3两倍
|
||||||
if max(bi_1.low, bi_3.low) < min(bi_1.high, bi_3.high) < bi_5.low:
|
if min_low < max(bi_1.low, bi_3.low) < min(bi_1.high, bi_3.high) < bi_5.low:
|
||||||
if bi_5.high == max_high:
|
if bi_5.high == max_high:
|
||||||
v = ChanSignals.LI0.value
|
v = ChanSignals.LI0.value # 类三买, 五笔
|
||||||
elif bi_4.low == min_low and bi_1.high == max_high \
|
elif bi_3.low == min_low and bi_1.high == max_high \
|
||||||
and bi_4.height > max(bi_1.height, bi_2.height, bi_3.height) \
|
and bi_4.height > max(bi_1.height, bi_2.height, bi_3.height) \
|
||||||
and bi_4.height > 2 * max(bi_2.height, bi_3.height):
|
and bi_4.height > 2 * max(bi_2.height, bi_3.height):
|
||||||
v = ChanSignals.LI0.value
|
v = ChanSignals.LI0.value # 类三买, 五笔
|
||||||
|
|
||||||
# 向上三角扩张中枢
|
# # 向上三角扩张中枢
|
||||||
if bi_1.high < bi_3.high < bi_5.high and bi_1.low > bi_3.low > bi_5.low:
|
# if bi_1.high < bi_3.high < bi_5.high and bi_1.low > bi_3.low > bi_5.low:
|
||||||
v = ChanSignals.LJ0.value
|
# v = ChanSignals.LJ0.value
|
||||||
|
#
|
||||||
# 向上三角收敛中枢
|
# # 向上三角收敛中枢
|
||||||
if bi_1.high > bi_3.high > bi_5.high and bi_1.low < bi_3.low < bi_5.low:
|
# if bi_1.high > bi_3.high > bi_5.high and bi_1.low < bi_3.low < bi_5.low:
|
||||||
v = ChanSignals.LK0.value
|
# v = ChanSignals.LK0.value
|
||||||
|
|
||||||
# 上涨线段,寻找顶背驰
|
# 上涨线段,寻找顶背驰
|
||||||
elif direction == 1:
|
elif direction == 1:
|
||||||
# aAb式顶背驰
|
# aAb式顶背驰,类一卖
|
||||||
if min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) and min_low == bi_1.low and bi_5.height < bi_1.height:
|
if min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) and min_low == bi_1.low and bi_5.height < bi_1.height:
|
||||||
if (max_high == bi_3.high and bi_5.high > bi_1.high) or (max_high == bi_5.high):
|
if (max_high == bi_3.high and bi_5.high > bi_1.high) or (max_high == bi_5.high):
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.SA0.value # k3='基础形态', v1='顶背驰', v2='五笔aAb式'
|
||||||
|
|
||||||
# 类趋势顶背驰
|
# 类趋势顶背驰,类一卖
|
||||||
if min_low == bi_1.low and max_high == bi_5.high \
|
if min_low == bi_1.low and max_high == bi_5.high \
|
||||||
and bi_5.height < max(bi_1.height, bi_3.height) \
|
and bi_5.height < max(bi_1.height, bi_3.height) \
|
||||||
and bi_5.atan < max(bi_1.atan, bi_3.atan) \
|
and bi_5.atan < max(bi_1.atan, bi_3.atan) \
|
||||||
and bi_4.low > bi_2.high:
|
and bi_4.low > bi_2.high:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.SA0.value # k3='基础形态', v1='顶背驰', v2='五笔类趋势')
|
||||||
|
|
||||||
# 下颈线突破
|
# 下颈线突破
|
||||||
if (max_high == bi_1.high and bi_5.low < max(bi_1.low, bi_2.low) < bi_5.high < max_high) \
|
if (max_high == bi_1.high and bi_5.low < max(bi_1.low, bi_2.low) < bi_5.high < max_high) \
|
||||||
or (max_high == bi_3.high and bi_5.low < bi_3.low < bi_5.high < max_high):
|
or (max_high == bi_3.high and bi_5.low < bi_3.low < bi_5.high < max_high):
|
||||||
v = ChanSignals.SG0.value
|
return ChanSignals.SG0.value # k3='基础形态', v1='下颈线突破', v2='五笔')
|
||||||
|
|
||||||
# 五笔三卖,要求bi_5.low是最低点,中枢可能是1~3
|
# 五笔三卖,要求bi_5.low是最低点,中枢可能是1~3
|
||||||
if min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low) > bi_5.high:
|
if min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low) > bi_5.high:
|
||||||
if bi_5.low == min_low:
|
if bi_5.low == min_low:
|
||||||
v = ChanSignals.SI0.value
|
return ChanSignals.SI0.value
|
||||||
elif bi_4.high == max_high and bi_1.low == min_low \
|
elif bi_3.high == max_high and bi_1.low == min_low \
|
||||||
and bi_4.height > max(bi_1.height, bi_2.height, bi_3.height)\
|
and bi_4.height > max(bi_1.height, bi_2.height, bi_3.height) \
|
||||||
and bi_4.height > 2 * max(bi_2.height,bi_3.height):
|
and bi_4.height > 2 * max(bi_2.height, bi_3.height):
|
||||||
v = ChanSignals.SI0.value
|
return ChanSignals.SI0.value # k3='基础形态', v1='类三卖', v2='五笔')
|
||||||
# elif bi_1.high == max_high and bi_1.low == min_low:
|
# elif bi_1.high == max_high and bi_1.low == min_low:
|
||||||
|
|
||||||
# 向下三角扩张中枢
|
# # 向下三角扩张中枢
|
||||||
if bi_1.high < bi_3.high < bi_5.high and bi_1.low > bi_3.low > bi_5.low:
|
# if bi_1.high < bi_3.high < bi_5.high and bi_1.low > bi_3.low > bi_5.low:
|
||||||
v = ChanSignals.SJ0.value
|
# v = ChanSignals.SJ0.value
|
||||||
|
#
|
||||||
# 向下三角收敛中枢
|
# # 向下三角收敛中枢
|
||||||
if bi_1.high > bi_3.high > bi_5.high and bi_1.low < bi_3.low < bi_5.low:
|
# if bi_1.high > bi_3.high > bi_5.high and bi_1.low < bi_3.low < bi_5.low:
|
||||||
v = ChanSignals.SK0.value
|
# v = ChanSignals.SK0.value
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def check_chan_xt_seven_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
def check_chan_xt_seven_bi(kline, bi_list: List[ChanObject]):
|
||||||
"""
|
"""
|
||||||
识别当前7笔的形态
|
识别当前7笔的形态
|
||||||
:param cur_duan:
|
:param cur_duan:
|
||||||
@ -371,80 +456,80 @@ def check_chan_xt_seven_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
|||||||
# aAbcd式底背驰, d.高度斜率 小于 b.高度斜率
|
# aAbcd式底背驰, d.高度斜率 小于 b.高度斜率
|
||||||
if min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) > bi_6.high \
|
if min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) > bi_6.high \
|
||||||
and bi_7.height < bi_5.height and bi_7.atan <= bi_5.atan:
|
and bi_7.height < bi_5.height and bi_7.atan <= bi_5.atan:
|
||||||
v = ChanSignals.LA0.value
|
v = ChanSignals.LA0.value # k3='基础形态', v1='底背驰', v2='七笔aAbcd式')
|
||||||
|
|
||||||
# abcAd式底背驰
|
# abcAd式底背驰
|
||||||
if bi_2.low > min(bi_4.high, bi_6.high) > max(bi_4.low, bi_6.low) \
|
if bi_2.low > min(bi_4.high, bi_6.high) > max(bi_4.low, bi_6.low) \
|
||||||
and bi_7.height < (bi_1.high - bi_3.low) \
|
and bi_7.height < (bi_1.high - bi_3.low) \
|
||||||
and bi_7.atan < (bi_1.atan + bi_3.atan) / 2:
|
and bi_7.atan < (bi_1.atan + bi_3.atan) / 2:
|
||||||
v = ChanSignals.LA0.value
|
v = ChanSignals.LA0.value # k3='基础形态', v1='底背驰', v2='七笔abcAd式')
|
||||||
|
|
||||||
# aAb式底背驰
|
# aAb式底背驰
|
||||||
if min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) \
|
if min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) \
|
||||||
and bi_7.height < bi_1.height and bi_7.atan <= bi_1.atan:
|
and bi_7.height < bi_1.height and bi_7.atan <= bi_1.atan:
|
||||||
v = ChanSignals.LA0.value
|
v = ChanSignals.LA0.value # k3='基础形态', v1='底背驰', v2='七笔aAb式'
|
||||||
|
|
||||||
# 类趋势底背驰
|
# 类趋势底背驰
|
||||||
if bi_2.low > bi_4.high and bi_4.low > bi_6.high \
|
if bi_2.low > bi_4.high and bi_4.low > bi_6.high \
|
||||||
and bi_7.height < max(bi_5.height, bi_3.height, bi_1.height)\
|
and bi_7.height < max(bi_5.height, bi_3.height, bi_1.height) \
|
||||||
and bi_7.atan < max(bi_5.atan, bi_3.atan, bi_1.atan):
|
and bi_7.atan < max(bi_5.atan, bi_3.atan, bi_1.atan):
|
||||||
v = ChanSignals.LA0.value
|
v = ChanSignals.LA0.value # k3='基础形态', v1='底背驰', v2='七笔类趋势'
|
||||||
|
|
||||||
# 向上中枢完成
|
# 向上中枢完成
|
||||||
if bi_4.low == min_low and min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low) \
|
if bi_4.low == min_low and min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low) \
|
||||||
and min(bi_5.high, bi_7.high) > max(bi_5.low, bi_7.low) \
|
and min(bi_5.high, bi_7.high) > max(bi_5.low, bi_7.low) \
|
||||||
and max(bi_4.high, bi_6.high) > min(bi_3.high, bi_4.high):
|
and max(bi_4.high, bi_6.high) > min(bi_3.high, bi_4.high):
|
||||||
if max(bi_1.low, bi_3.low) < max(bi_5.high, bi_7.high):
|
if max(bi_1.low, bi_3.low) < max(bi_5.high, bi_7.high):
|
||||||
v = ChanSignals.LH0.value
|
v = ChanSignals.LH0.value # k3='基础形态', v1='向上中枢完成', v2='七笔')
|
||||||
|
|
||||||
# 七笔三买,567回调
|
# 七笔三买,567回调 :1~3构成中枢,最低点在1~3,最高点在5~7,5~7的最低点大于1~3的最高点
|
||||||
if bi_5.high == max_high and bi_5.high > bi_7.high \
|
if bi_5.high == max_high and bi_5.high > bi_7.high \
|
||||||
and bi_5.low > bi_7.low > min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low):
|
and bi_5.low > bi_7.low > min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low):
|
||||||
v = ChanSignals.LI0.value
|
v = ChanSignals.LI0.value # k3='基础形态', v1='类三买', v2='七笔'
|
||||||
#
|
|
||||||
elif bi_7.direction == 1:
|
elif bi_7.direction == 1:
|
||||||
# 顶背驰
|
# 顶背驰
|
||||||
if bi_1.low == min_low and bi_7.high == max_high:
|
if bi_1.low == min_low and bi_7.high == max_high:
|
||||||
# aAbcd式顶背驰
|
# aAbcd式顶背驰
|
||||||
if bi_6.low > min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) \
|
if bi_6.low > min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) \
|
||||||
and bi_7.height < bi_5.height and bi_7.atan <= bi_5.atan:
|
and bi_7.height < bi_5.height and bi_7.atan <= bi_5.atan:
|
||||||
v = ChanSignals.SA0.value
|
v = ChanSignals.SA0.value # k3='基础形态', v1='顶背驰', v2='七笔aAbcd式'
|
||||||
|
|
||||||
# abcAd式顶背驰
|
# abcAd式顶背驰
|
||||||
if min(bi_4.high, bi_6.high) > max(bi_4.low, bi_6.low) > bi_2.high \
|
if min(bi_4.high, bi_6.high) > max(bi_4.low, bi_6.low) > bi_2.high \
|
||||||
and bi_7.height < (bi_3.high - bi_1.low) \
|
and bi_7.height < (bi_3.high - bi_1.low) \
|
||||||
and bi_7.atan < (bi_1.atan + bi_3.atan) / 2:
|
and bi_7.atan < (bi_1.atan + bi_3.atan) / 2:
|
||||||
v = ChanSignals.SA0.value
|
v = ChanSignals.SA0.value # k3='基础形态', v1='顶背驰', v2='七笔abcAd式'
|
||||||
|
|
||||||
# aAb式顶背驰
|
# aAb式顶背驰
|
||||||
if min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) \
|
if min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) \
|
||||||
and bi_7.height < bi_1.height and bi_7.atan <= bi_1.atan:
|
and bi_7.height < bi_1.height and bi_7.atan <= bi_1.atan:
|
||||||
v = ChanSignals.SA0.value
|
v = ChanSignals.SA0.value # k3='基础形态', v1='顶背驰', v2='七笔aAb式'
|
||||||
|
|
||||||
# 类趋势顶背驰
|
# 类趋势顶背驰
|
||||||
if bi_2.high < bi_4.low and bi_4.high < bi_6.low \
|
if bi_2.high < bi_4.low and bi_4.high < bi_6.low \
|
||||||
and bi_7.height < max(bi_5.height, bi_3.height, bi_1.height)\
|
and bi_7.height < max(bi_5.height, bi_3.height, bi_1.height) \
|
||||||
and bi_7.atan < max(bi_5.atan, bi_3.atan, bi_1.atan):
|
and bi_7.atan < max(bi_5.atan, bi_3.atan, bi_1.atan):
|
||||||
v = ChanSignals.SA0.value
|
v = ChanSignals.SA0.value # k3='基础形态', v1='顶背驰', v2='七笔类趋势'
|
||||||
|
|
||||||
# 向下中枢完成
|
# 向下中枢完成
|
||||||
if bi_4.high == max_high and min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low) \
|
if bi_4.high == max_high and min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low) \
|
||||||
and min(bi_5.high, bi_7.high) > max(bi_5.low, bi_7.low) \
|
and min(bi_5.high, bi_7.high) > max(bi_5.low, bi_7.low) \
|
||||||
and min(bi_4.low, bi_6.low) < max(bi_3.low, bi_4.low):
|
and min(bi_4.low, bi_6.low) < max(bi_3.low, bi_4.low):
|
||||||
if min(bi_1.high, bi_3.high) > min(bi_5.low, bi_7.low):
|
if min(bi_1.high, bi_3.high) > min(bi_5.low, bi_7.low):
|
||||||
v = ChanSignals.SH0.value
|
v = ChanSignals.SH0.value # k3='基础形态', v1='向下中枢完成', v2='七笔'
|
||||||
|
|
||||||
# 七笔三卖,567回调,中枢可能在1~3
|
# 七笔三卖,567回调 1~3构成中枢,最高点在1~3,最低点在5~7,5~7的最高点小于1~3的最低点
|
||||||
if bi_5.low == min_low and bi_5.low < bi_7.low \
|
if bi_5.low == min_low and bi_5.low < bi_7.low \
|
||||||
and min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low) > bi_7.high > bi_5.high:
|
and min(bi_1.high, bi_3.high) > max(bi_1.low, bi_3.low) > bi_7.high > bi_5.high:
|
||||||
v = ChanSignals.SI0.value
|
v = ChanSignals.SI0.value # k3='基础形态', v1='类三卖', v2='七笔'
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def check_chan_xt_nine_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
def check_chan_xt_nine_bi(kline, bi_list: List[ChanObject]):
|
||||||
"""
|
"""
|
||||||
获取线段得形态(9分笔)
|
获取线段得买卖点(9分笔)
|
||||||
:param cur_duan:
|
:param cur_duan:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@ -460,72 +545,126 @@ def check_chan_xt_nine_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
|||||||
# 依据最后一笔得方向进行判断
|
# 依据最后一笔得方向进行判断
|
||||||
if direction == -1:
|
if direction == -1:
|
||||||
if min_low == bi_9.low and max_high == bi_1.high:
|
if min_low == bi_9.low and max_high == bi_1.high:
|
||||||
# aAbBc式底背驰
|
# aAb式类一买
|
||||||
if min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) > bi_6.high \
|
|
||||||
and min(bi_6.high, bi_8.high) > max(bi_6.low, bi_8.low) \
|
|
||||||
and min(bi_2.low, bi_4.low) > max(bi_6.high, bi_8.high) \
|
|
||||||
and bi_9.height < bi_5.height and bi_7.atan <= bi_5.atan:
|
|
||||||
v = ChanSignals.LA0.value
|
|
||||||
|
|
||||||
# aAb式底背驰
|
|
||||||
if min(bi_2.high, bi_4.high, bi_6.high, bi_8.high) > max(bi_2.low, bi_4.low, bi_6.low, bi_8.low) \
|
if min(bi_2.high, bi_4.high, bi_6.high, bi_8.high) > max(bi_2.low, bi_4.low, bi_6.low, bi_8.low) \
|
||||||
and bi_9.height < bi_1.height and bi_9.atan <= bi_1.atan \
|
and bi_9.height < bi_1.height and bi_9.atan <= bi_1.atan \
|
||||||
and bi_3.low >= bi_1.low and bi_7.high <= bi_9.high:
|
and bi_3.low >= bi_1.low and bi_7.high <= bi_9.high:
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.Q1L0.value # k3='类买卖点', v1='类一买', v2='九笔aAb式'
|
||||||
|
|
||||||
# aAbcd式底背驰
|
# aAbcd式类一买
|
||||||
if min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) > bi_8.high \
|
if min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) > bi_8.high \
|
||||||
and bi_9.height < bi_7.height and bi_9.atan <= bi_7.atan:
|
and bi_9.height < bi_7.height and bi_9.atan <= bi_7.atan:
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.Q1L0.value # k3='类买卖点', v1='类一买', v2='九笔aAbcd式'
|
||||||
|
|
||||||
# ABC式底背驰
|
# ABC式类一买
|
||||||
if bi_3.low < bi_1.low and bi_7.high > bi_9.high \
|
if bi_3.low < bi_1.low and bi_7.high > bi_9.high \
|
||||||
and min(bi_4.high, bi_6.high) > max(bi_4.low, bi_6.low) \
|
and min(bi_4.high, bi_6.high) > max(bi_4.low, bi_6.low) \
|
||||||
and (bi_1.high - bi_3.low) > (bi_7.high - bi_9.low):
|
and (bi_1.high - bi_3.low) > (bi_7.high - bi_9.low):
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.Q1L0.value # k3='类买卖点', v1='类一买', v2='九笔ABC式'
|
||||||
|
|
||||||
# 九笔三买(789回调)中枢可能在3~7内
|
# 类趋势一买
|
||||||
if min_low == bi_1.low and max_high == bi_9.high \
|
if bi_8.high < bi_6.low < bi_6.high < bi_4.high < bi_2.low \
|
||||||
and bi_9.low > min([x.high for x in [bi_3, bi_5, bi_7]]) > max([x.low for x in [bi_3, bi_5, bi_7]]):
|
and bi_9.atan < max([bi_1.atan, bi_3.atan, bi_5.atan, bi_7.atan]):
|
||||||
v = ChanSignals.LI0.value
|
return ChanSignals.Q1L0.value # k3='类买卖点', v1='类一买', v2='九笔类趋势'
|
||||||
|
|
||||||
|
# 9笔 aAbBc式类一买(2~4构成中枢A,6~8构成中枢B,9背驰)
|
||||||
|
if max_high == max(bi_1.high, bi_3.high) and min_low == bi_9.low \
|
||||||
|
and min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) > bi_6.high \
|
||||||
|
and min(bi_6.high, bi_8.high) > max(bi_6.low, bi_8.low) \
|
||||||
|
and min(bi_2.low, bi_4.low) > max(bi_6.high, bi_8.high) \
|
||||||
|
and bi_9.height < bi_5.height and bi_9.atan <= bi_5.atan:
|
||||||
|
return ChanSignals.Q1L0.value # k3='类买卖点', v1='类一买', v2='九笔aAb式')
|
||||||
|
|
||||||
|
# 九笔GG 类三买(1357构成中枢,最低点在3或5)
|
||||||
|
if max_high == bi_9.high > bi_9.low \
|
||||||
|
> max([x.high for x in [bi_1, bi_3, bi_5, bi_7]]) \
|
||||||
|
> min([x.high for x in [bi_1, bi_3, bi_5, bi_7]]) \
|
||||||
|
> max([x.low for x in [bi_1, bi_3, bi_5, bi_7]]) \
|
||||||
|
> min([x.low for x in [bi_3, bi_5]]) == min_low:
|
||||||
|
return ChanSignals.Q3L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三买', v2='九笔GG三买')
|
||||||
|
|
||||||
|
# 类三买(357构成中枢,8的力度小于2,9回调不跌破GG构成三买)
|
||||||
|
if bi_8.height < bi_2.height and max_high == bi_9.high > bi_9.low \
|
||||||
|
> max([x.high for x in [bi_3, bi_5, bi_7]]) \
|
||||||
|
> min([x.high for x in [bi_3, bi_5, bi_7]]) \
|
||||||
|
> max([x.low for x in [bi_3, bi_5, bi_7]]) > bi_1.low == min_low:
|
||||||
|
return ChanSignals.Q3L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三买', v2='九笔GG三买')
|
||||||
|
|
||||||
|
# # 九笔三买(789回调)中枢可能在3~7内
|
||||||
|
# if min_low == bi_1.low and max_high == bi_9.high \
|
||||||
|
# and bi_9.low > min([x.high for x in [bi_3, bi_5, bi_7]]) > max([x.low for x in [bi_3, bi_5, bi_7]]):
|
||||||
|
# v = ChanSignals.Q3L0.value
|
||||||
|
|
||||||
|
if min_low == bi_5.low and max_high == bi_1.high and bi_4.high < bi_2.low: # 前五笔构成向下类趋势
|
||||||
|
zd = max([x.low for x in [bi_5, bi_7]])
|
||||||
|
zg = min([x.high for x in [bi_5, bi_7]])
|
||||||
|
gg = max([x.high for x in [bi_5, bi_7]])
|
||||||
|
if zg > zd and bi_8.high > gg: # 567构成中枢,且8的高点大于gg
|
||||||
|
if bi_9.low > zg:
|
||||||
|
return ChanSignals.Q3L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三买', v2='九笔ZG三买')
|
||||||
|
|
||||||
|
# 类二买
|
||||||
|
if bi_9.high > gg > zg > bi_9.low > zd:
|
||||||
|
return ChanSignals.Q2L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二买', v2='九笔')
|
||||||
|
|
||||||
elif direction == 1:
|
elif direction == 1:
|
||||||
if max_high == bi_9.high and min_low == bi_1.low:
|
|
||||||
# aAbBc式顶背驰
|
|
||||||
if bi_6.low > min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) \
|
|
||||||
and min(bi_6.high, bi_8.high) > max(bi_6.low, bi_8.low) \
|
|
||||||
and max(bi_2.high, bi_4.high) < min(bi_6.low, bi_8.low) \
|
|
||||||
and bi_9.height < bi_5.height and bi_9.atan <= bi_5.atan:
|
|
||||||
v = ChanSignals.SA0.value
|
|
||||||
|
|
||||||
# aAb式顶背驰
|
# 倒9笔是最高点,倒一笔是最低点
|
||||||
|
if max_high == bi_9.high and min_low == bi_1.low:
|
||||||
|
|
||||||
|
# aAb式类一卖
|
||||||
if min(bi_2.high, bi_4.high, bi_6.high, bi_8.high) > max(bi_2.low, bi_4.low, bi_6.low, bi_8.low) \
|
if min(bi_2.high, bi_4.high, bi_6.high, bi_8.high) > max(bi_2.low, bi_4.low, bi_6.low, bi_8.low) \
|
||||||
and bi_9.height < bi_1.height and bi_9.atan <= bi_1.atan \
|
and bi_9.height < bi_1.height and bi_9.atan <= bi_1.atan \
|
||||||
and bi_3.high <= bi_1.high and bi_7.low >= bi_9.low:
|
and bi_3.high <= bi_1.high and bi_7.low >= bi_9.low:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2='九笔aAb式')
|
||||||
|
|
||||||
# aAbcd式顶背驰
|
# aAbcd式类一卖
|
||||||
if bi_8.low > min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) \
|
if bi_8.low > min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) \
|
||||||
and bi_9.height < bi_7.height and bi_9.atan <= bi_7.atan:
|
and bi_9.height < bi_7.height and bi_9.atan <= bi_7.atan:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2='九笔aAbcd式')
|
||||||
|
|
||||||
# ABC式顶背驰
|
# ABC式类一卖
|
||||||
if bi_3.high > bi_1.high and bi_7.low < bi_9.low \
|
if bi_3.high > bi_1.high and bi_7.low < bi_9.low \
|
||||||
and min(bi_4.high, bi_6.high) > max(bi_4.low, bi_6.low) \
|
and min(bi_4.high, bi_6.high) > max(bi_4.low, bi_6.low) \
|
||||||
and (bi_3.high - bi_1.low) > (bi_9.high - bi_7.low):
|
and (bi_3.high - bi_1.low) > (bi_9.high - bi_7.low):
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2='九笔ABC式')
|
||||||
|
|
||||||
# 九笔三卖
|
# 类趋势类一卖
|
||||||
|
if bi_8.low > bi_6.high > bi_6.low > bi_4.high > bi_4.low > bi_2.high \
|
||||||
|
and bi_9.atan < max([bi_1.atan, bi_3.atan, bi_5.atan, bi_7.atan]):
|
||||||
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2='九笔类趋势')
|
||||||
|
|
||||||
|
# aAbBc式类一卖
|
||||||
|
if max_high == bi_9.high and min_low == min(bi_1.low, bi_3.low) \
|
||||||
|
and bi_6.low > min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) \
|
||||||
|
and min(bi_6.high, bi_8.high) > max(bi_6.low, bi_8.low) \
|
||||||
|
and max(bi_2.high, bi_4.high) < min(bi_6.low, bi_8.low) \
|
||||||
|
and bi_9.height < bi_5.height and bi_9.atan <= bi_5.atan:
|
||||||
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2='九笔aAbBc式')
|
||||||
|
|
||||||
|
# 九笔类三卖
|
||||||
if max_high == bi_1.high and min_low == bi_9.low \
|
if max_high == bi_1.high and min_low == bi_9.low \
|
||||||
and bi_9.high < max([x.low for x in [bi_3, bi_5, bi_7]]) < min([x.high for x in [bi_3, bi_5, bi_7]]):
|
and bi_9.high < max([x.low for x in [bi_3, bi_5, bi_7]]) < min([x.high for x in [bi_3, bi_5, bi_7]]):
|
||||||
v = ChanSignals.SI0.value
|
return ChanSignals.Q3S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三卖', v2='九笔')
|
||||||
|
|
||||||
|
if min_low == bi_1.low and max_high == bi_5.high and bi_2.high < bi_4.low: # 前五笔构成向上类趋势
|
||||||
|
zd = max([x.low for x in [bi_5, bi_7]])
|
||||||
|
zg = min([x.high for x in [bi_5, bi_7]])
|
||||||
|
dd = min([x.low for x in [bi_5, bi_7]])
|
||||||
|
if zg > zd and bi_8.low < dd: # 567构成中枢,且8的低点小于dd
|
||||||
|
if bi_9.high < zd:
|
||||||
|
return ChanSignals.Q3S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三卖', v2='九笔ZD三卖')
|
||||||
|
|
||||||
|
# 类二卖
|
||||||
|
if dd < zd <= bi_9.high < zg:
|
||||||
|
return ChanSignals.Q2S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二卖', v2='九笔')
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def check_chan_xt_eleven_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
def check_chan_xt_eleven_bi(kline, bi_list: List[ChanObject]):
|
||||||
"""
|
"""
|
||||||
获取线段得背驰形态(含11个分笔)
|
获取线段得的类买卖点(含11个分笔)
|
||||||
:param cur_duan:
|
:param cur_duan:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@ -538,95 +677,126 @@ def check_chan_xt_eleven_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
|||||||
max_high = max([x.high for x in bi_list])
|
max_high = max([x.high for x in bi_list])
|
||||||
min_low = min([x.low for x in bi_list])
|
min_low = min([x.low for x in bi_list])
|
||||||
|
|
||||||
|
# 11笔向下,寻找买点
|
||||||
if direction == -1:
|
if direction == -1:
|
||||||
|
# 1笔最高,11笔最低
|
||||||
if min_low == bi_11.low and max_high == bi_1.high:
|
if min_low == bi_11.low and max_high == bi_1.high:
|
||||||
# aAbBc式底背驰,bi_2-bi_6构成A
|
|
||||||
if min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) > bi_8.high \
|
|
||||||
and min(bi_8.high, bi_10.high) > max(bi_8.low, bi_10.low) \
|
|
||||||
and min(bi_2.low, bi_4.low, bi_6.low) > max(bi_8.high, bi_10.high) \
|
|
||||||
and bi_11.height < bi_7.height and bi_11.atan <= bi_7.atan:
|
|
||||||
v = ChanSignals.LA0.value
|
|
||||||
|
|
||||||
# aAbBc式底背驰,bi_6-bi_10构成B
|
# ABC式类一买,A5B3C3
|
||||||
if min(bi_2.high, bi_4.high) > max(bi_2.low, bi_4.low) > bi_6.high \
|
|
||||||
and min(bi_6.high, bi_8.high, bi_10.high) > max(bi_6.low, bi_8.low, bi_10.low) \
|
|
||||||
and min(bi_2.low, bi_4.low) > max(bi_6.high, bi_8.high, bi_10.high) \
|
|
||||||
and bi_11.height < bi_5.height and bi_11.atan <= bi_5.atan:
|
|
||||||
v = ChanSignals.LA0.value
|
|
||||||
|
|
||||||
# ABC式底背驰,A5B3C3
|
|
||||||
if bi_5.low == min([x.low for x in [bi_1, bi_3, bi_5]]) \
|
if bi_5.low == min([x.low for x in [bi_1, bi_3, bi_5]]) \
|
||||||
and bi_9.low > bi_11.low and bi_9.high > bi_11.high \
|
and bi_9.low > bi_11.low and bi_9.high > bi_11.high \
|
||||||
and bi_8.high > bi_6.low and bi_1.high - bi_5.low > bi_9.high - bi_11.low:
|
and bi_8.high > bi_6.low and bi_1.high - bi_5.low > bi_9.high - bi_11.low:
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.Q1L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一买', v2="11笔A5B3C3式")
|
||||||
# C内部背驰
|
|
||||||
if bi_11.height < bi_9.height:
|
|
||||||
v = ChanSignals.LB0.value
|
|
||||||
|
|
||||||
# ABC式底背驰,A3B3C5
|
# ABC式类一买,A3B3C5
|
||||||
if bi_1.high > bi_3.high and bi_1.low > bi_3.low \
|
if bi_1.high > bi_3.high and bi_1.low > bi_3.low \
|
||||||
and bi_7.high == max([x.high for x in [bi_7, bi_9, bi_11]]) \
|
and bi_7.high == max([x.high for x in [bi_7, bi_9, bi_11]]) \
|
||||||
and bi_6.high > bi_4.low and bi_1.high - bi_3.low > bi_7.high - bi_11.low:
|
and bi_6.high > bi_4.low and bi_1.high - bi_3.low > bi_7.high - bi_11.low:
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.Q1L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一买', v2="11笔A3B3C5式")
|
||||||
# C内部背驰
|
|
||||||
if bi_11.height < max(bi_9.height, bi_7.height) and bi_11.atan <= max(bi_9.atan, bi_7.atan):
|
|
||||||
v = ChanSignals.LB0.value
|
|
||||||
|
|
||||||
# ABC式底背驰,A3B5C3
|
# ABC式类一买,A3B5C3
|
||||||
if bi_1.low > bi_3.low and min(bi_4.high, bi_6.high, bi_8.high) > max(bi_4.low, bi_6.low, bi_8.low) \
|
if bi_1.low > bi_3.low and min(bi_4.high, bi_6.high, bi_8.high) > max(bi_4.low, bi_6.low, bi_8.low) \
|
||||||
and bi_9.high > bi_11.high and bi_1.high - bi_3.low > bi_9.high - bi_11.low:
|
and bi_9.high > bi_11.high and bi_1.high - bi_3.low > bi_9.high - bi_11.low:
|
||||||
v = ChanSignals.LA0.value
|
v = ChanSignals.Q1L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一买', v2="11笔A3B5C3式")
|
||||||
# C内部背驰
|
|
||||||
if bi_11.height < max(bi_9.height, bi_7.height) and bi_11.atan <= max(bi_9.atan, bi_7.atan):
|
|
||||||
v = ChanSignals.LB0.value
|
|
||||||
|
|
||||||
|
# a1Ab式类一买,a1(1~7构成的类趋势)
|
||||||
|
if bi_2.low > bi_4.high > bi_4.low > bi_6.high > bi_5.low > bi_7.low and bi_10.high > bi_8.low:
|
||||||
|
return ChanSignals.Q1L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一买', v2="11笔a1Ab式")
|
||||||
|
|
||||||
|
# 类二买:1~9构成类趋势,11不创新低,斜率低于9
|
||||||
|
if min_low == bi_9.low < bi_8.high < bi_6.low < bi_6.high < bi_4.low < bi_4.high < bi_2.low < bi_1.high == max_high \
|
||||||
|
and bi_11.low > bi_9.low and bi_9.atan > bi_11.atan:
|
||||||
|
return ChanSignals.Q2L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二买', v2="11笔")
|
||||||
|
|
||||||
|
# 类二买(1~7构成盘整背驰,246构成下跌中枢,9/11构成上涨中枢,且上涨中枢ZG大于下跌中枢ZG)
|
||||||
|
if bi_7.atan < bi_1.atan and min_low == bi_7.low < max([x.low for x in [bi_2, bi_4, bi_6]]) \
|
||||||
|
< min([x.high for x in [bi_2, bi_4, bi_6]]) < max(
|
||||||
|
[x.high for x in [bi_9, bi_11]]) < bi_1.high == max_high \
|
||||||
|
and bi_11.low > min([x.low for x in [bi_2, bi_4, bi_6]]) \
|
||||||
|
and min([x.high for x in [bi_9, bi_11]]) > max([x.low for x in [bi_9, bi_11]]):
|
||||||
|
return ChanSignals.Q2L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二买', v2="11笔")
|
||||||
|
|
||||||
|
# 类二买(1~7为区间极值,9~11构成上涨中枢,上涨中枢GG大于4~6的最大值,上涨中枢DD大于4~6的最小值)
|
||||||
|
if max_high == bi_1.high and min_low == bi_7.low \
|
||||||
|
and min(bi_9.high, bi_11.high) > max(bi_9.low, bi_11.low) \
|
||||||
|
and max(bi_11.high, bi_9.high) > max(bi_4.high, bi_6.high) \
|
||||||
|
and min(bi_9.low, bi_11.low) > min(bi_4.low, bi_6.low):
|
||||||
|
return ChanSignals.Q2L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二买', v2="11笔")
|
||||||
|
|
||||||
|
# 类三买(1~9构成大级别中枢,10离开,11回调不跌破GG)
|
||||||
|
gg = max([x.high for x in [bi_1, bi_2, bi_3]])
|
||||||
|
zg = min([x.high for x in [bi_1, bi_2, bi_3]])
|
||||||
|
zd = max([x.low for x in [bi_1, bi_2, bi_3]])
|
||||||
|
dd = min([x.low for x in [bi_1, bi_2, bi_3]])
|
||||||
|
if max_high == bi_11.high and bi_11.low > zg > zd \
|
||||||
|
and gg > bi_5.low and gg > bi_7.low and gg > bi_9.low \
|
||||||
|
and dd < bi_5.high and dd < bi_7.high and dd < bi_9.high:
|
||||||
|
return ChanSignals.Q3L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三买', v2="11笔GG三买")
|
||||||
|
|
||||||
|
# 11笔向上,寻找卖点
|
||||||
elif direction == 1:
|
elif direction == 1:
|
||||||
|
# 1笔最低,11笔最高
|
||||||
if max_high == bi_11.high and min_low == bi_1.low:
|
if max_high == bi_11.high and min_low == bi_1.low:
|
||||||
# aAbBC式顶背驰,bi_2-bi_6构成A
|
|
||||||
if bi_8.low > min(bi_2.high, bi_4.high, bi_6.high) >= max(bi_2.low, bi_4.low, bi_6.low) \
|
|
||||||
and min(bi_8.high, bi_10.high) >= max(bi_8.low, bi_10.low) \
|
|
||||||
and max(bi_2.high, bi_4.high, bi_6.high) < min(bi_8.low, bi_10.low) \
|
|
||||||
and bi_11.height < bi_7.height and bi_11.atan <= bi_7.atan:
|
|
||||||
v = ChanSignals.SA0.value
|
|
||||||
|
|
||||||
# aAbBC式顶背驰,bi_6-bi_10构成B
|
|
||||||
if bi_6.low > min(bi_2.high, bi_4.high) >= max(bi_2.low, bi_4.low) \
|
|
||||||
and min(bi_6.high, bi_8.high, bi_10.high) >= max(bi_6.low, bi_8.low, bi_10.low) \
|
|
||||||
and max(bi_2.high, bi_4.high) < min(bi_6.low, bi_8.low, bi_10.low) \
|
|
||||||
and bi_11.height < bi_7.height and bi_11.atan <= bi_7.atan:
|
|
||||||
v = ChanSignals.SA0.value
|
|
||||||
|
|
||||||
# ABC式顶背驰,A5B3C3
|
# ABC式顶背驰,A5B3C3
|
||||||
if bi_5.high == max([bi_1.high, bi_3.high, bi_5.high]) and bi_9.low < bi_11.low and bi_9.high < bi_11.high \
|
if bi_5.high == max([bi_1.high, bi_3.high, bi_5.high]) and bi_9.low < bi_11.low and bi_9.high < bi_11.high \
|
||||||
and bi_8.low < bi_6.high and bi_11.high - bi_9.low < bi_5.high - bi_1.low:
|
and bi_8.low < bi_6.high and bi_11.high - bi_9.low < bi_5.high - bi_1.low:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2="11笔A5B3C3式")
|
||||||
# C内部背驰
|
|
||||||
if bi_11.height < bi_9.height and bi_11.atan <= bi_9.atan:
|
|
||||||
v = ChanSignals.SB0.value
|
|
||||||
|
|
||||||
# ABC式顶背驰,A3B3C5
|
# ABC式顶背驰,A3B3C5
|
||||||
if bi_7.low == min([bi_11.low, bi_9.low, bi_7.low]) and bi_1.high < bi_3.high and bi_1.low < bi_3.low \
|
if bi_7.low == min([bi_11.low, bi_9.low, bi_7.low]) and bi_1.high < bi_3.high and bi_1.low < bi_3.low \
|
||||||
and bi_6.low < bi_4.high and bi_11.high - bi_7.low < bi_3.high - bi_1.low:
|
and bi_6.low < bi_4.high and bi_11.high - bi_7.low < bi_3.high - bi_1.low:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2="11笔A3B3C5式")
|
||||||
# C内部背驰
|
|
||||||
if bi_11.height < max(bi_9.height, bi_7.height) and bi_11.atan <= max(bi_9.atan, bi_7.atan):
|
|
||||||
v = ChanSignals.SB0.value
|
|
||||||
|
|
||||||
# ABC式顶背驰,A3B5C3
|
# ABC式顶背驰,A3B5C3
|
||||||
if bi_1.high < bi_3.high and min(bi_4.high, bi_6.high, bi_8.high) > max(bi_4.low, bi_6.low, bi_8.low) \
|
if bi_1.high < bi_3.high and min(bi_4.high, bi_6.high, bi_8.high) > max(bi_4.low, bi_6.low, bi_8.low) \
|
||||||
and bi_9.low < bi_11.low and bi_3.high - bi_1.low > bi_11.high - bi_9.low:
|
and bi_9.low < bi_11.low and bi_3.high - bi_1.low > bi_11.high - bi_9.low:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value
|
||||||
# C内部背驰
|
|
||||||
if bi_11.height < max(bi_9.height, bi_7.height) and bi_11.atan <= max(bi_9.atan, bi_7.atan):
|
# a1Ab式类一卖,a1(1~7构成的类趋势)
|
||||||
v = ChanSignals.SB0.value
|
if bi_2.high < bi_4.low < bi_4.high < bi_6.low < bi_5.high < bi_7.high and bi_10.low < bi_8.high:
|
||||||
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2="11笔a1Ab式")
|
||||||
|
|
||||||
|
# 类二卖:1~9构成类趋势,11不创新高
|
||||||
|
if max_high == bi_9.high > bi_8.low > bi_6.high > bi_6.low > bi_4.high > bi_4.low > bi_2.high > bi_1.low == min_low \
|
||||||
|
and bi_11.high < bi_9.high and bi_9.atan > bi_11.atan:
|
||||||
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二卖', v2="11笔")
|
||||||
|
|
||||||
|
# 类二卖(1~7构成盘整背驰,246构成上涨中枢,9/11构成下跌中枢,且下跌中枢DD小于上涨中枢ZD)
|
||||||
|
if bi_7.atan < bi_1.atan and max_high == bi_7.high \
|
||||||
|
> min([x.high for x in [bi_2, bi_4, bi_6]]) \
|
||||||
|
> max([x.low for x in [bi_2, bi_4, bi_6]]) \
|
||||||
|
> min([x.low for x in [bi_9, bi_11]]) \
|
||||||
|
> bi_1.low == min_low \
|
||||||
|
and bi_11.high < max([x.high for x in [bi_2, bi_4, bi_6]]) \
|
||||||
|
and max([x.low for x in [bi_9, bi_11]]) < min([x.high for x in [bi_9, bi_11]]):
|
||||||
|
return ChanSignals.Q2S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二卖', v2="11笔")
|
||||||
|
|
||||||
|
# 类二卖(1~7为区间极值,9~11构成下跌中枢,下跌中枢DD小于4~6的最小值,下跌中枢GG小于4~6的最大值)
|
||||||
|
if min_low == bi_1.low and max_high == bi_7.high \
|
||||||
|
and max(bi_9.low, bi_11.low) < min(bi_9.high, bi_11.high) \
|
||||||
|
and min(bi_11.low, bi_9.low) < min(bi_4.low, bi_6.low) \
|
||||||
|
and max(bi_9.high, bi_11.high) < max(bi_4.high, bi_6.high):
|
||||||
|
return ChanSignals.Q2S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二卖', v2="11笔")
|
||||||
|
|
||||||
|
# 类三卖(1~9构成大级别中枢,10离开,11回调不涨破DD)
|
||||||
|
gg = min([x.low for x in [bi_1, bi_2, bi_3]])
|
||||||
|
zg = max([x.low for x in [bi_1, bi_2, bi_3]])
|
||||||
|
zd = min([x.high for x in [bi_1, bi_2, bi_3]])
|
||||||
|
dd = max([x.high for x in [bi_1, bi_2, bi_3]])
|
||||||
|
if min_low == bi_11.low and bi_11.high < zd < zg \
|
||||||
|
and dd < bi_5.high and dd < bi_7.high and dd < bi_9.high \
|
||||||
|
and gg > bi_5.low and gg > bi_7.low and gg > bi_9.low:
|
||||||
|
return ChanSignals.Q3S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三卖', v2="11笔GG三买")
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def check_chan_xt_thirteen_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
def check_chan_xt_thirteen_bi(kline, bi_list: List[ChanObject]):
|
||||||
"""
|
"""
|
||||||
获取线段得背驰形态(含13个分笔)
|
获取线段得形态(含13个分笔)
|
||||||
:param cur_duan:
|
:param kline:
|
||||||
|
:param bi_list: 由远及近的十三笔
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
v = ChanSignals.Other.value
|
v = ChanSignals.Other.value
|
||||||
@ -641,78 +811,48 @@ def check_chan_xt_thirteen_bi(kline: CtaLineBar, bi_list: List[ChanObject]):
|
|||||||
# 下跌线段时,判断背驰类型
|
# 下跌线段时,判断背驰类型
|
||||||
if direction == -1:
|
if direction == -1:
|
||||||
if min_low == bi_13.low and max_high == bi_1.high:
|
if min_low == bi_13.low and max_high == bi_1.high:
|
||||||
# aAbBc式底背驰,bi_2-bi_6构成A,bi_8-bi_12构成B
|
# ABC式类一买,A5B3C5
|
||||||
if min(bi_2.high, bi_4.high, bi_6.high) > max(bi_2.low, bi_4.low, bi_6.low) > bi_8.high \
|
|
||||||
and min(bi_8.high, bi_10.high, bi_12.high) > max(bi_8.low, bi_10.low, bi_12.low) \
|
|
||||||
and min(bi_2.low, bi_4.low, bi_6.low) > max(bi_8.high, bi_10.high, bi_12.high) \
|
|
||||||
and bi_13.height < bi_7.height and bi_13.atan <= bi_7.atan:
|
|
||||||
v = ChanSignals.LA0.value
|
|
||||||
|
|
||||||
# ABC式底背驰,A5B3C5
|
|
||||||
if bi_5.low < min(bi_1.low, bi_3.low) and bi_9.high > max(bi_11.high, bi_13.high) \
|
if bi_5.low < min(bi_1.low, bi_3.low) and bi_9.high > max(bi_11.high, bi_13.high) \
|
||||||
and bi_8.high > bi_6.low and bi_1.high - bi_5.low > bi_9.high - bi_13.low:
|
and bi_8.high > bi_6.low and bi_1.high - bi_5.low > bi_9.high - bi_13.low:
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.Q1L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一买', v2="13笔A5B3C5式")
|
||||||
|
|
||||||
if bi_13.height < max(bi_11.height, bi_9.height) and bi_13.atan <= max(bi_11.atan, bi_9.atan):
|
# ABC式类一买,A3B5C5
|
||||||
v = ChanSignals.LB0.value
|
|
||||||
|
|
||||||
# ABC式底背驰,A3B5C5
|
|
||||||
if bi_3.low < min(bi_1.low, bi_5.low) and bi_9.high > max(bi_11.high, bi_13.high) \
|
if bi_3.low < min(bi_1.low, bi_5.low) and bi_9.high > max(bi_11.high, bi_13.high) \
|
||||||
and min(bi_4.high, bi_6.high, bi_8.high) > max(bi_4.low, bi_6.low, bi_8.low) \
|
and min(bi_4.high, bi_6.high, bi_8.high) > max(bi_4.low, bi_6.low, bi_8.low) \
|
||||||
and bi_1.high - bi_3.low > bi_9.high - bi_13.low:
|
and bi_1.high - bi_3.low > bi_9.high - bi_13.low:
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.Q1L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一买', v2="13笔A3B5C5式")
|
||||||
|
|
||||||
if bi_13.height < max(bi_11.height, bi_9.height) and bi_13.atan <= max(bi_11.atan, bi_9.atan):
|
|
||||||
v = ChanSignals.LB0.value
|
|
||||||
|
|
||||||
# ABC式底背驰,A5B5C3
|
# ABC式底背驰,A5B5C3
|
||||||
if bi_5.low < min(bi_1.low, bi_3.low) and bi_11.high > max(bi_9.high, bi_13.high) \
|
if bi_5.low < min(bi_1.low, bi_3.low) and bi_11.high > max(bi_9.high, bi_13.high) \
|
||||||
and min(bi_6.high, bi_8.high, bi_10.high) > max(bi_6.low, bi_8.low, bi_10.low) \
|
and min(bi_6.high, bi_8.high, bi_10.high) > max(bi_6.low, bi_8.low, bi_10.low) \
|
||||||
and bi_1.high - bi_5.low > bi_11.high - bi_13.low:
|
and bi_1.high - bi_5.low > bi_11.high - bi_13.low:
|
||||||
v = ChanSignals.LA0.value
|
return ChanSignals.Q1L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一买', v2="13笔A5B5C3式")
|
||||||
|
|
||||||
if bi_13.height < bi_11.height and bi_13.atan <= bi_11.atan:
|
|
||||||
v = ChanSignals.LB0.value
|
|
||||||
|
|
||||||
# 上涨线段时,判断背驰类型
|
# 上涨线段时,判断背驰类型
|
||||||
elif direction == 1:
|
elif direction == 1:
|
||||||
if max_high == bi_13.high and min_low == bi_1.low:
|
if max_high == bi_13.high and min_low == bi_1.low:
|
||||||
# aAbBC式顶背驰,bi_2-bi_6构成A,bi_8-bi_12构成B
|
|
||||||
if bi_8.low > min(bi_2.high, bi_4.high, bi_6.high) >= max(bi_2.low, bi_4.low, bi_6.low) \
|
|
||||||
and min(bi_8.high, bi_10.high, bi_12.high) >= max(bi_8.low, bi_10.low, bi_12.low) \
|
|
||||||
and max(bi_2.high, bi_4.high, bi_6.high) < min(bi_8.low, bi_10.low, bi_12.low) \
|
|
||||||
and bi_13.height < bi_7.height and bi_13.atan <= bi_7.atan:
|
|
||||||
v = ChanSignals.SA0.value
|
|
||||||
|
|
||||||
# ABC式顶背驰,A5B3C5
|
# ABC式顶背驰,A5B3C5
|
||||||
if bi_5.high > max(bi_3.high, bi_1.high) and bi_9.low < min(bi_11.low, bi_13.low) \
|
if bi_5.high > max(bi_3.high, bi_1.high) and bi_9.low < min(bi_11.low, bi_13.low) \
|
||||||
and bi_8.low < bi_6.high and bi_5.high - bi_1.low > bi_13.high - bi_9.low:
|
and bi_8.low < bi_6.high and bi_5.high - bi_1.low > bi_13.high - bi_9.low:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2="13笔A5B3C5式")
|
||||||
# C内部顶背驰,形成双重顶背驰
|
|
||||||
if bi_13.height < max(bi_11.height, bi_9.height) and bi_13.atan <= max(bi_11.atan, bi_9.atan):
|
|
||||||
v = ChanSignals.SB0.value
|
|
||||||
|
|
||||||
# ABC式顶背驰,A3B5C5
|
# ABC式顶背驰,A3B5C5
|
||||||
if bi_3.high > max(bi_5.high, bi_1.high) and bi_9.low < min(bi_11.low, bi_13.low) \
|
if bi_3.high > max(bi_5.high, bi_1.high) and bi_9.low < min(bi_11.low, bi_13.low) \
|
||||||
and min(bi_4.high, bi_6.high, bi_8.high) > max(bi_4.low, bi_6.low, bi_8.low) \
|
and min(bi_4.high, bi_6.high, bi_8.high) > max(bi_4.low, bi_6.low, bi_8.low) \
|
||||||
and bi_3.high - bi_1.low > bi_13.high - bi_9.low:
|
and bi_3.high - bi_1.low > bi_13.high - bi_9.low:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2="13笔A3B5C5式")
|
||||||
# C内部顶背驰,形成双重顶背驰
|
|
||||||
if bi_13.height < max(bi_11.height, bi_9.height) and bi_13.atan <= max(bi_11.atan, bi_9.atan):
|
|
||||||
v = ChanSignals.SB0.value
|
|
||||||
|
|
||||||
# ABC式顶背驰,A5B5C3
|
# ABC式顶背驰,A5B5C3
|
||||||
if bi_5.high > max(bi_3.high, bi_1.high) and bi_11.low < min(bi_9.low, bi_13.low) \
|
if bi_5.high > max(bi_3.high, bi_1.high) and bi_11.low < min(bi_9.low, bi_13.low) \
|
||||||
and min(bi_6.high, bi_8.high, bi_10.high) > max(bi_6.low, bi_8.low, bi_10.low) \
|
and min(bi_6.high, bi_8.high, bi_10.high) > max(bi_6.low, bi_8.low, bi_10.low) \
|
||||||
and bi_5.high - bi_1.low > bi_13.high - bi_11.low:
|
and bi_5.high - bi_1.low > bi_13.high - bi_11.low:
|
||||||
v = ChanSignals.SA0.value
|
return ChanSignals.Q1S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类一卖', v2="13笔A5B5C3式")
|
||||||
# C内部顶背驰,形成双重顶背驰
|
|
||||||
if bi_13.height < bi_11.height and bi_13.atan <= bi_11.atan:
|
|
||||||
v = ChanSignals.SB0.value
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def check_pzbc_1st(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
# def check_pzbc_1st(big_kline, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
||||||
|
def check_pzbc_1st(big_kline, small_kline, signal_direction: Direction):
|
||||||
"""
|
"""
|
||||||
判断中枢盘整背驰1买/1卖信号
|
判断中枢盘整背驰1买/1卖信号
|
||||||
big_kline当前线段为调整段,与信号方向相反,线段具有盘整一个中枢,
|
big_kline当前线段为调整段,与信号方向相反,线段具有盘整一个中枢,
|
||||||
@ -806,7 +946,8 @@ def check_pzbc_1st(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None],
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_qsbc_1st(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
# def check_qsbc_1st(big_kline, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
||||||
|
def check_qsbc_1st(big_kline, small_kline, signal_direction: Direction):
|
||||||
"""
|
"""
|
||||||
判断趋势背驰1买/1卖信号
|
判断趋势背驰1买/1卖信号
|
||||||
big_kline当前线段为趋势,与信号方向相反,线段具有2个中枢,
|
big_kline当前线段为趋势,与信号方向相反,线段具有2个中枢,
|
||||||
@ -890,7 +1031,8 @@ def check_qsbc_1st(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None],
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_pz3bc_1st(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
# def check_pz3bc_1st(big_kline, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
||||||
|
def check_pz3bc_1st(big_kline, small_kline, signal_direction: Direction):
|
||||||
"""
|
"""
|
||||||
判断三卖后盘整背驰一买/三买后盘整背驰1卖信号
|
判断三卖后盘整背驰一买/三买后盘整背驰1卖信号
|
||||||
big_kline当前线段与信号方向相反,线段具有盘整一个中枢,离开中枢的一笔力度与三买/卖信号后的一笔对比(高度、斜率)
|
big_kline当前线段与信号方向相反,线段具有盘整一个中枢,离开中枢的一笔力度与三买/卖信号后的一笔对比(高度、斜率)
|
||||||
@ -966,7 +1108,8 @@ def check_pz3bc_1st(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None],
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_qjt_1st(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
# def check_qjt_1st(big_kline, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
||||||
|
def check_qjt_1st(big_kline, small_kline, signal_direction: Direction):
|
||||||
"""
|
"""
|
||||||
判断区间套一买/区间套1卖信号
|
判断区间套一买/区间套1卖信号
|
||||||
big_kline当前线段与信号方向相反,线段具有盘整一个中枢,
|
big_kline当前线段与信号方向相反,线段具有盘整一个中枢,
|
||||||
@ -1038,7 +1181,8 @@ def check_qjt_1st(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None], s
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_qsbc_2nd(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
# def check_qsbc_2nd(big_kline, small_kline: Union[CtaLineBar, None], signal_direction: Direction):
|
||||||
|
def check_qsbc_2nd(big_kline, small_kline, signal_direction: Direction):
|
||||||
"""
|
"""
|
||||||
判断趋势背驰1买/1卖后的二买、二卖信号
|
判断趋势背驰1买/1卖后的二买、二卖信号
|
||||||
big_kline当前线段为趋势,与信号方向相反,线段具有2个中枢,
|
big_kline当前线段为趋势,与信号方向相反,线段具有2个中枢,
|
||||||
@ -1136,8 +1280,9 @@ def check_qsbc_2nd(big_kline: CtaLineBar, small_kline: Union[CtaLineBar, None],
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def check_zs_3rd(big_kline: CtaLineBar,
|
# : Union[CtaLineBar, None]
|
||||||
small_kline: Union[CtaLineBar, None],
|
def check_zs_3rd(big_kline,
|
||||||
|
small_kline,
|
||||||
signal_direction: Direction,
|
signal_direction: Direction,
|
||||||
first_zs: bool = True,
|
first_zs: bool = True,
|
||||||
all_zs: bool = True):
|
all_zs: bool = True):
|
||||||
@ -1181,7 +1326,7 @@ def check_zs_3rd(big_kline: CtaLineBar,
|
|||||||
zs_list = [zs for zs in big_kline.bi_zs_list[-3:] if zs.start >= big_kline.cur_duan.start]
|
zs_list = [zs for zs in big_kline.bi_zs_list[-3:] if zs.start >= big_kline.cur_duan.start]
|
||||||
zs_num = len(zs_list)
|
zs_num = len(zs_list)
|
||||||
# 是否现在线段得首个中枢后的三买三卖
|
# 是否现在线段得首个中枢后的三买三卖
|
||||||
if first_zs and zs_num> 1:
|
if first_zs and zs_num > 1:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
# 中枢需要与当前线段有交集[部分交集、或中枢完全在当前段内形成]
|
# 中枢需要与当前线段有交集[部分交集、或中枢完全在当前段内形成]
|
||||||
|
@ -112,7 +112,7 @@ def download_adjust_factor():
|
|||||||
login_msg = bs.login()
|
login_msg = bs.login()
|
||||||
if login_msg.error_code != '0':
|
if login_msg.error_code != '0':
|
||||||
print(f'证券宝登录错误代码:{login_msg.error_code}, 错误信息:{login_msg.error_msg}')
|
print(f'证券宝登录错误代码:{login_msg.error_code}, 错误信息:{login_msg.error_msg}')
|
||||||
return
|
return None
|
||||||
|
|
||||||
for k, v in base_dict.items():
|
for k, v in base_dict.items():
|
||||||
if v.get('类型') != '股票':
|
if v.get('类型') != '股票':
|
||||||
@ -127,6 +127,7 @@ def download_adjust_factor():
|
|||||||
save_data_to_pkb2(factor_dict, cache_file_name)
|
save_data_to_pkb2(factor_dict, cache_file_name)
|
||||||
print(f'保存除权除息至文件:{cache_file_name}')
|
print(f'保存除权除息至文件:{cache_file_name}')
|
||||||
|
|
||||||
|
return factor_dict
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
download_adjust_factor()
|
download_adjust_factor()
|
||||||
|
@ -415,7 +415,7 @@ class PbGateway(BaseGateway):
|
|||||||
def process_timer_event(self, event) -> None:
|
def process_timer_event(self, event) -> None:
|
||||||
""""""
|
""""""
|
||||||
self.count += 1
|
self.count += 1
|
||||||
if self.count < 2:
|
if self.count < 5:
|
||||||
return
|
return
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
|
||||||
@ -1116,10 +1116,26 @@ class PbTdApi(object):
|
|||||||
'{}{}.dbf'.format(
|
'{}{}.dbf'.format(
|
||||||
PB_FILE_NAMES.get('accounts'),
|
PB_FILE_NAMES.get('accounts'),
|
||||||
self.trading_date)))
|
self.trading_date)))
|
||||||
|
|
||||||
|
copy_dbf = os.path.abspath(os.path.join(self.account_folder,
|
||||||
|
'{}{}_{}.dbf'.format(
|
||||||
|
PB_FILE_NAMES.get('accounts'),
|
||||||
|
self.trading_date,
|
||||||
|
datetime.now().strftime('%H%M'))))
|
||||||
try:
|
try:
|
||||||
|
if not os.path.exists(account_dbf):
|
||||||
|
return
|
||||||
|
if os.path.exists(copy_dbf):
|
||||||
|
os.remove(copy_dbf)
|
||||||
|
|
||||||
|
# =》转移至于新文件
|
||||||
|
os.rename(account_dbf, copy_dbf)
|
||||||
|
if not os.path.exists(copy_dbf):
|
||||||
|
return
|
||||||
|
|
||||||
# dbf => 资金帐号信息
|
# dbf => 资金帐号信息
|
||||||
self.gateway.write_log(f'扫描资金帐号信息:{account_dbf}')
|
self.gateway.write_log(f'扫描资金帐号信息:{copy_dbf}')
|
||||||
table = dbf.Table(account_dbf, codepage='cp936')
|
table = dbf.Table(copy_dbf, codepage='cp936')
|
||||||
table.open(dbf.READ_ONLY)
|
table.open(dbf.READ_ONLY)
|
||||||
for data in table:
|
for data in table:
|
||||||
# ["资金账户"]
|
# ["资金账户"]
|
||||||
@ -1137,6 +1153,8 @@ class PbTdApi(object):
|
|||||||
|
|
||||||
table.close()
|
table.close()
|
||||||
self.warning_dict.pop('query_account', None)
|
self.warning_dict.pop('query_account', None)
|
||||||
|
if os.path.exists(copy_dbf):
|
||||||
|
os.remove(copy_dbf)
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
err_msg = f'dbf扫描资金帐号异常:{str(ex)}'
|
err_msg = f'dbf扫描资金帐号异常:{str(ex)}'
|
||||||
@ -1200,10 +1218,24 @@ class PbTdApi(object):
|
|||||||
'{}{}.dbf'.format(
|
'{}{}.dbf'.format(
|
||||||
PB_FILE_NAMES.get('positions'),
|
PB_FILE_NAMES.get('positions'),
|
||||||
self.trading_date)))
|
self.trading_date)))
|
||||||
|
|
||||||
|
copy_dbf = os.path.abspath(os.path.join(self.account_folder,
|
||||||
|
'{}{}_{}.dbf'.format(
|
||||||
|
PB_FILE_NAMES.get('positions'),
|
||||||
|
self.trading_date,
|
||||||
|
datetime.now().strftime('%H%M'))))
|
||||||
try:
|
try:
|
||||||
|
if not os.path.exists(position_dbf):
|
||||||
|
return
|
||||||
|
if os.path.exists(copy_dbf):
|
||||||
|
os.remove(copy_dbf)
|
||||||
|
os.rename(position_dbf, copy_dbf)
|
||||||
|
if not os.path.exists(copy_dbf):
|
||||||
|
return
|
||||||
|
|
||||||
# dbf => 股票持仓信息
|
# dbf => 股票持仓信息
|
||||||
self.gateway.write_log(f'扫描股票持仓信息:{position_dbf}')
|
self.gateway.write_log(f'扫描股票持仓信息:{copy_dbf}')
|
||||||
table = dbf.Table(position_dbf, codepage='cp936')
|
table = dbf.Table(copy_dbf, codepage='cp936')
|
||||||
table.open(dbf.READ_ONLY)
|
table.open(dbf.READ_ONLY)
|
||||||
for data in table:
|
for data in table:
|
||||||
if str(data.zjzh).strip() != self.userid:
|
if str(data.zjzh).strip() != self.userid:
|
||||||
@ -1242,6 +1274,9 @@ class PbTdApi(object):
|
|||||||
table.close()
|
table.close()
|
||||||
self.warning_dict.pop('query_position', None)
|
self.warning_dict.pop('query_position', None)
|
||||||
|
|
||||||
|
if os.path.exists(copy_dbf):
|
||||||
|
os.remove(copy_dbf)
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
|
||||||
err_msg = f'dbf扫描股票持仓异常:{str(ex)}'
|
err_msg = f'dbf扫描股票持仓异常:{str(ex)}'
|
||||||
@ -1325,6 +1360,8 @@ class PbTdApi(object):
|
|||||||
PB_FILE_NAMES.get('orders'),
|
PB_FILE_NAMES.get('orders'),
|
||||||
self.trading_date)))
|
self.trading_date)))
|
||||||
try:
|
try:
|
||||||
|
if not os.path.exists(orders_dbf):
|
||||||
|
return
|
||||||
# dbf => 股票委托信息
|
# dbf => 股票委托信息
|
||||||
self.gateway.write_log(f'扫描股票委托信息:{orders_dbf}')
|
self.gateway.write_log(f'扫描股票委托信息:{orders_dbf}')
|
||||||
table = dbf.Table(orders_dbf, codepage='cp936')
|
table = dbf.Table(orders_dbf, codepage='cp936')
|
||||||
@ -1506,8 +1543,9 @@ class PbTdApi(object):
|
|||||||
'{}{}.dbf'.format(
|
'{}{}.dbf'.format(
|
||||||
PB_FILE_NAMES.get('update_orders'),
|
PB_FILE_NAMES.get('update_orders'),
|
||||||
self.trading_date)))
|
self.trading_date)))
|
||||||
# dbf => 所有委托记录
|
|
||||||
try:
|
try:
|
||||||
|
if not os.path.exists(orders_dbf):
|
||||||
|
return
|
||||||
# dbf => 所有成交记录
|
# dbf => 所有成交记录
|
||||||
self.gateway.write_log(f'扫描所有委托查询:{orders_dbf}')
|
self.gateway.write_log(f'扫描所有委托查询:{orders_dbf}')
|
||||||
table = dbf.Table(orders_dbf, codepage='cp936')
|
table = dbf.Table(orders_dbf, codepage='cp936')
|
||||||
@ -1686,6 +1724,8 @@ class PbTdApi(object):
|
|||||||
PB_FILE_NAMES.get('trades'),
|
PB_FILE_NAMES.get('trades'),
|
||||||
self.trading_date)))
|
self.trading_date)))
|
||||||
try:
|
try:
|
||||||
|
if not os.path.exists(trades_dbf):
|
||||||
|
return
|
||||||
# dbf => 股票成交信息
|
# dbf => 股票成交信息
|
||||||
self.gateway.write_log(f'扫描股票成交信息:{trades_dbf}')
|
self.gateway.write_log(f'扫描股票成交信息:{trades_dbf}')
|
||||||
table = dbf.Table(trades_dbf, codepage='cp936')
|
table = dbf.Table(trades_dbf, codepage='cp936')
|
||||||
@ -1824,6 +1864,8 @@ class PbTdApi(object):
|
|||||||
self.trading_date)))
|
self.trading_date)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if not os.path.exists(trades_dbf):
|
||||||
|
return
|
||||||
# dbf => 所有成交记录
|
# dbf => 所有成交记录
|
||||||
self.gateway.write_log(f'扫描所有成交记录:{trades_dbf}')
|
self.gateway.write_log(f'扫描所有成交记录:{trades_dbf}')
|
||||||
table = dbf.Table(trades_dbf, codepage='cp936')
|
table = dbf.Table(trades_dbf, codepage='cp936')
|
||||||
@ -1981,6 +2023,9 @@ class PbTdApi(object):
|
|||||||
dbf_file = os.path.abspath(os.path.join(self.order_folder,
|
dbf_file = os.path.abspath(os.path.join(self.order_folder,
|
||||||
'{}{}.dbf'.format(PB_FILE_NAMES.get('send_order'), self.trading_date)))
|
'{}{}.dbf'.format(PB_FILE_NAMES.get('send_order'), self.trading_date)))
|
||||||
try:
|
try:
|
||||||
|
if not os.path.exists(dbf_file):
|
||||||
|
return
|
||||||
|
|
||||||
table = dbf.Table(dbf_file, codepage='cp936')
|
table = dbf.Table(dbf_file, codepage='cp936')
|
||||||
table.open(dbf.READ_ONLY)
|
table.open(dbf.READ_ONLY)
|
||||||
for record in table:
|
for record in table:
|
||||||
|
@ -214,85 +214,20 @@ class ChanSignals(Enum):
|
|||||||
LB0 = "LB0~双重底背驰"
|
LB0 = "LB0~双重底背驰"
|
||||||
LG0 = "LG0~上颈线突破"
|
LG0 = "LG0~上颈线突破"
|
||||||
LH0 = "LH0~向上中枢完成"
|
LH0 = "LH0~向上中枢完成"
|
||||||
LI0 = "LI0~三买"
|
LI0 = "LI0~类三买"
|
||||||
LJ0 = "LJ0~向上三角扩张中枢"
|
LJ0 = "LJ0~向上三角扩张中枢"
|
||||||
LK0 = "LK0~向上三角收敛中枢"
|
LK0 = "LK0~向上三角收敛中枢"
|
||||||
LL0 = "LL0~向上平台型中枢"
|
LL0 = "LL0~向上平台型中枢"
|
||||||
# ------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
LA1 = "LA1~底背驰特例一"
|
|
||||||
LA2 = "LA2~底背驰特例二"
|
|
||||||
LA3 = "LA3~底背驰特例三"
|
|
||||||
|
|
||||||
LB1 = "LB1~双重底背驰特例一"
|
|
||||||
LB2 = "LB2~双重底背驰特例二"
|
|
||||||
LB3 = "LB3~双重底背驰特例三"
|
|
||||||
|
|
||||||
LG1 = "LG1~上颈线突破特例一"
|
|
||||||
LG2 = "LG2~上颈线突破特例二"
|
|
||||||
LG3 = "LG3~上颈线突破特例三"
|
|
||||||
|
|
||||||
LH1 = "LH1~向上中枢完成特例一"
|
|
||||||
LH2 = "LH2~向上中枢完成特例二"
|
|
||||||
LH3 = "LH3~向上中枢完成特例三"
|
|
||||||
|
|
||||||
LI1 = "LI1~三买特例一"
|
|
||||||
LI2 = "LI2~三买特例二"
|
|
||||||
LI3 = "LI3~三买特例三"
|
|
||||||
|
|
||||||
LJ1 = "LJ1~向上三角扩张中枢特例一"
|
|
||||||
LJ2 = "LJ2~向上三角扩张中枢特例二"
|
|
||||||
LJ3 = "LJ3~向上三角扩张中枢特例三"
|
|
||||||
|
|
||||||
LK1 = "LK1~向上三角收敛中枢特例一"
|
|
||||||
LK2 = "LK2~向上三角收敛中枢特例二"
|
|
||||||
LK3 = "LK3~向上三角收敛中枢特例三"
|
|
||||||
|
|
||||||
LL1 = "LL1~向上平台型中枢特例一"
|
|
||||||
LL2 = "LL2~向上平台型中枢特例二"
|
|
||||||
LL3 = "LL3~向上平台型中枢特例三"
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------------------------------------------
|
||||||
SA0 = "SA0~顶背驰"
|
SA0 = "SA0~顶背驰"
|
||||||
SB0 = "SB0~双重顶背驰"
|
SB0 = "SB0~双重顶背驰"
|
||||||
SG0 = "SG0~下颈线突破"
|
SG0 = "SG0~下颈线突破"
|
||||||
SH0 = "SH0~向下中枢完成"
|
SH0 = "SH0~向下中枢完成"
|
||||||
SI0 = "SI0~三卖"
|
SI0 = "SI0~类三卖"
|
||||||
SJ0 = "SJ0~向下三角扩张中枢"
|
SJ0 = "SJ0~向下三角扩张中枢"
|
||||||
SK0 = "SK0~向下三角收敛中枢"
|
SK0 = "SK0~向下三角收敛中枢"
|
||||||
SL0 = "SL0~向下平台型中枢"
|
SL0 = "SL0~向下平台型中枢"
|
||||||
# ------------------------------------------------------------------------------------------------------------------
|
|
||||||
SA1 = "SA1~顶背驰特例一"
|
|
||||||
SA2 = "SA2~顶背驰特例二"
|
|
||||||
SA3 = "SA3~顶背驰特例三"
|
|
||||||
|
|
||||||
SB1 = "SB1~双重顶背驰特例一"
|
|
||||||
SB2 = "SB2~双重顶背驰特例二"
|
|
||||||
SB3 = "SB3~双重顶背驰特例三"
|
|
||||||
|
|
||||||
SG1 = "SG1~下颈线突破特例一"
|
|
||||||
SG2 = "SG2~下颈线突破特例二"
|
|
||||||
SG3 = "SG3~下颈线突破特例三"
|
|
||||||
|
|
||||||
SH1 = "SH1~向下中枢完成特例一"
|
|
||||||
SH2 = "SH2~向下中枢完成特例二"
|
|
||||||
SH3 = "SH3~向下中枢完成特例三"
|
|
||||||
|
|
||||||
SI1 = "SI1~三卖特例一"
|
|
||||||
SI2 = "SI2~三卖特例二"
|
|
||||||
SI3 = "SI3~三卖特例三"
|
|
||||||
|
|
||||||
SJ1 = "SJ1~向下三角扩张中枢特例一"
|
|
||||||
SJ2 = "SJ2~向下三角扩张中枢特例二"
|
|
||||||
SJ3 = "SJ3~向下三角扩张中枢特例三"
|
|
||||||
|
|
||||||
SK1 = "SK1~向下三角收敛中枢特例一"
|
|
||||||
SK2 = "SK2~向下三角收敛中枢特例二"
|
|
||||||
SK3 = "SK3~向下三角收敛中枢特例三"
|
|
||||||
|
|
||||||
SL1 = "SL1~向下平台型中枢特例一"
|
|
||||||
SL2 = "SL2~向下平台型中枢特例二"
|
|
||||||
SL3 = "SL3~向下平台型中枢特例三"
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------
|
||||||
# 信号值编码规则:
|
# 信号值编码规则:
|
||||||
@ -304,16 +239,24 @@ class ChanSignals(Enum):
|
|||||||
# 三笔形态信号
|
# 三笔形态信号
|
||||||
# --------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------
|
||||||
X3LA0 = "X3LA0~向下不重合"
|
X3LA0 = "X3LA0~向下不重合"
|
||||||
X3LB0 = "X3LB0~向下奔走型中枢"
|
X3LB0 = "X3LB0~向下奔走型"
|
||||||
X3LC0 = "X3LC0~向下三角收敛中枢"
|
X3LC0 = "X3LC0~向下收敛"
|
||||||
X3LD0 = "X3LD0~向下三角扩张中枢"
|
X3LD0 = "X3LD0~向下扩张"
|
||||||
X3LE0 = "X3LE0~向下盘背中枢"
|
X3LE0 = "X3LE0~向下盘背"
|
||||||
X3LF0 = "X3LF0~向下无背中枢"
|
X3LF0 = "X3LF0~向下无背"
|
||||||
|
|
||||||
X3SA0 = "X3SA0~向上不重合"
|
X3SA0 = "X3SA0~向上不重合"
|
||||||
X3SB0 = "X3SB0~向上奔走型中枢"
|
X3SB0 = "X3SB0~向上奔走型"
|
||||||
X3SC0 = "X3SC0~向上三角收敛中枢"
|
X3SC0 = "X3SC0~向上收敛"
|
||||||
X3SD0 = "X3SD0~向上三角扩张中枢"
|
X3SD0 = "X3SD0~向上扩张"
|
||||||
X3SE0 = "X3SE0~向上盘背中枢"
|
X3SE0 = "X3SE0~向上盘背"
|
||||||
X3SF0 = "X3SF0~向上无背中枢"
|
X3SF0 = "X3SF0~向上无背"
|
||||||
|
|
||||||
|
# 趋势类买卖点
|
||||||
|
Q1L0 = "Q1L0~趋势类一买"
|
||||||
|
Q2L0 = "Q2L0~趋势类二买"
|
||||||
|
Q3L0 = "Q2L0~趋势类三买"
|
||||||
|
|
||||||
|
Q1S0 = "Q1S0~趋势类一卖"
|
||||||
|
Q2S0 = "Q2S0~趋势类二卖"
|
||||||
|
Q3S0 = "Q2S0~趋势类三卖"
|
||||||
|
@ -171,6 +171,8 @@ class MainEngine:
|
|||||||
gateway = self.get_gateway(gateway_name)
|
gateway = self.get_gateway(gateway_name)
|
||||||
if gateway:
|
if gateway:
|
||||||
return gateway.get_default_setting()
|
return gateway.get_default_setting()
|
||||||
|
else:
|
||||||
|
self.write_error(f'获取网格设置时,找不到{gateway_name}')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_all_gateway_names(self) -> List[str]:
|
def get_all_gateway_names(self) -> List[str]:
|
||||||
@ -209,6 +211,8 @@ class MainEngine:
|
|||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
msg = f'gateway:{gateway_name}启动连接失败:{str(ex)}'
|
msg = f'gateway:{gateway_name}启动连接失败:{str(ex)}'
|
||||||
self.write_log(msg=msg)
|
self.write_log(msg=msg)
|
||||||
|
else:
|
||||||
|
self.write_error(f'连接{gateway_name}时,系统找不到{gateway_name}')
|
||||||
|
|
||||||
def subscribe(self, req: SubscribeRequest, gateway_name: str) -> None:
|
def subscribe(self, req: SubscribeRequest, gateway_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
@ -219,6 +223,8 @@ class MainEngine:
|
|||||||
gateway = self.get_gateway(gateway_name)
|
gateway = self.get_gateway(gateway_name)
|
||||||
if gateway:
|
if gateway:
|
||||||
gateway.subscribe(req)
|
gateway.subscribe(req)
|
||||||
|
else:
|
||||||
|
self.write_error(f'订阅合约时,找不到{gateway_name}')
|
||||||
else:
|
else:
|
||||||
for gateway in self.gateways.values():
|
for gateway in self.gateways.values():
|
||||||
if gateway:
|
if gateway:
|
||||||
@ -239,6 +245,7 @@ class MainEngine:
|
|||||||
if gateway:
|
if gateway:
|
||||||
return gateway.send_order(req)
|
return gateway.send_order(req)
|
||||||
else:
|
else:
|
||||||
|
self.write_error(f'发送委托时,找不到{gateway_name}')
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def cancel_order(self, req: CancelRequest, gateway_name: str) -> bool:
|
def cancel_order(self, req: CancelRequest, gateway_name: str) -> bool:
|
||||||
@ -253,6 +260,8 @@ class MainEngine:
|
|||||||
gateway = self.get_gateway(gateway_name)
|
gateway = self.get_gateway(gateway_name)
|
||||||
if gateway:
|
if gateway:
|
||||||
return gateway.cancel_order(req)
|
return gateway.cancel_order(req)
|
||||||
|
else:
|
||||||
|
self.write_error(f'撤单时,找不到{gateway_name}')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def send_orders(self, reqs: Sequence[OrderRequest], gateway_name: str) -> List[str]:
|
def send_orders(self, reqs: Sequence[OrderRequest], gateway_name: str) -> List[str]:
|
||||||
@ -263,6 +272,7 @@ class MainEngine:
|
|||||||
if gateway:
|
if gateway:
|
||||||
return gateway.send_orders(reqs)
|
return gateway.send_orders(reqs)
|
||||||
else:
|
else:
|
||||||
|
self.write_error(f'批量发单时,找不到{gateway_name}')
|
||||||
return ["" for req in reqs]
|
return ["" for req in reqs]
|
||||||
|
|
||||||
def cancel_orders(self, reqs: Sequence[CancelRequest], gateway_name: str) -> None:
|
def cancel_orders(self, reqs: Sequence[CancelRequest], gateway_name: str) -> None:
|
||||||
@ -271,6 +281,8 @@ class MainEngine:
|
|||||||
gateway = self.get_gateway(gateway_name)
|
gateway = self.get_gateway(gateway_name)
|
||||||
if gateway:
|
if gateway:
|
||||||
gateway.cancel_orders(reqs)
|
gateway.cancel_orders(reqs)
|
||||||
|
else:
|
||||||
|
self.write_error(f'批量撤单时,找不到{gateway_name}')
|
||||||
|
|
||||||
def query_history(self, req: HistoryRequest, gateway_name: str) -> Optional[List[BarData]]:
|
def query_history(self, req: HistoryRequest, gateway_name: str) -> Optional[List[BarData]]:
|
||||||
"""
|
"""
|
||||||
@ -280,7 +292,7 @@ class MainEngine:
|
|||||||
if gateway:
|
if gateway:
|
||||||
return gateway.query_history(req)
|
return gateway.query_history(req)
|
||||||
else:
|
else:
|
||||||
self.write_error(f'网关为空,请检查合约得网关是否与连接得网关一致')
|
self.write_error(f'找不到网关{gateway_name},请检查合约得网关是否与连接得网关一致')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
|
@ -135,6 +135,7 @@ class OrderData(BaseData):
|
|||||||
symbol: str
|
symbol: str
|
||||||
exchange: Exchange
|
exchange: Exchange
|
||||||
orderid: str
|
orderid: str
|
||||||
|
name: str = ""
|
||||||
sys_orderid: str = ""
|
sys_orderid: str = ""
|
||||||
accountid: str = ""
|
accountid: str = ""
|
||||||
type: OrderType = OrderType.LIMIT
|
type: OrderType = OrderType.LIMIT
|
||||||
@ -153,6 +154,8 @@ class OrderData(BaseData):
|
|||||||
self.vt_symbol = f"{self.symbol}.{self.exchange.value}"
|
self.vt_symbol = f"{self.symbol}.{self.exchange.value}"
|
||||||
self.vt_orderid = f"{self.gateway_name}.{self.orderid}"
|
self.vt_orderid = f"{self.gateway_name}.{self.orderid}"
|
||||||
self.vt_accountid = f"{self.gateway_name}.{self.accountid}"
|
self.vt_accountid = f"{self.gateway_name}.{self.accountid}"
|
||||||
|
if len(self.name) == 0:
|
||||||
|
self.name = self.vt_symbol
|
||||||
|
|
||||||
def is_active(self) -> bool:
|
def is_active(self) -> bool:
|
||||||
"""
|
"""
|
||||||
@ -184,6 +187,7 @@ class TradeData(BaseData):
|
|||||||
exchange: Exchange
|
exchange: Exchange
|
||||||
orderid: str
|
orderid: str
|
||||||
tradeid: str
|
tradeid: str
|
||||||
|
name: str = ""
|
||||||
sys_orderid: str = ""
|
sys_orderid: str = ""
|
||||||
accountid: str = ""
|
accountid: str = ""
|
||||||
|
|
||||||
@ -208,7 +212,8 @@ class TradeData(BaseData):
|
|||||||
self.vt_orderid = f"{self.gateway_name}.{self.orderid}"
|
self.vt_orderid = f"{self.gateway_name}.{self.orderid}"
|
||||||
self.vt_tradeid = f"{self.gateway_name}.{self.tradeid}"
|
self.vt_tradeid = f"{self.gateway_name}.{self.tradeid}"
|
||||||
self.vt_accountid = f"{self.gateway_name}.{self.accountid}"
|
self.vt_accountid = f"{self.gateway_name}.{self.accountid}"
|
||||||
|
if len(self.name) == 0:
|
||||||
|
self.name = self.vt_symbol
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PositionData(BaseData):
|
class PositionData(BaseData):
|
||||||
|
@ -347,6 +347,9 @@ def get_csv_last_dt(file_name, dt_index=0, dt_format='%Y-%m-%d %H:%M:%S', line_l
|
|||||||
:param line_length: 行数据的长度
|
:param line_length: 行数据的长度
|
||||||
:return: None,文件不存在,或者时间格式不正确
|
:return: None,文件不存在,或者时间格式不正确
|
||||||
"""
|
"""
|
||||||
|
if not os.path.exists(file_name):
|
||||||
|
return False
|
||||||
|
|
||||||
with open(file_name, 'r') as f:
|
with open(file_name, 'r') as f:
|
||||||
f_size = os.path.getsize(file_name)
|
f_size = os.path.getsize(file_name)
|
||||||
if f_size < line_length:
|
if f_size < line_length:
|
||||||
@ -1442,3 +1445,4 @@ def get_remote_file(remote_ip, remote_file_path, mode='rb'):
|
|||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print(u'打开远程目录异常:{}'.format(str(ex)))
|
print(u'打开远程目录异常:{}'.format(str(ex)))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user