forked from Vespa314/chan.py
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
vespa
committed
Feb 8, 2022
1 parent
25052d0
commit 0181ac3
Showing
34 changed files
with
969 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class CBi_Config: | ||
def __init__(self, is_strict=True): | ||
self.is_strict = is_strict |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
class CBSPointConfig: | ||
def __init__(self, **args): | ||
self.b_conf = CPointConfig(**args) | ||
self.s_conf = CPointConfig(**args) | ||
|
||
def GetStragetyPara(self, is_buy, k): | ||
if is_buy: | ||
return self.b_conf.GetStragetyPara(k) | ||
else: | ||
return self.s_conf.GetStragetyPara(k) | ||
|
||
|
||
class CPointConfig: | ||
def __init__(self, | ||
divergence_rate, | ||
min_zs_cnt, | ||
max_bs2_rate, | ||
macd_algo, | ||
bs1_peak, | ||
bs_type, | ||
stragety_para, | ||
bsp2_follow_1, | ||
bsp3_follow_1, | ||
bsp2s_follow_2, | ||
strict_bsp3, | ||
score_thred, | ||
): | ||
self.divergence_rate = divergence_rate | ||
self.min_zs_cnt = min_zs_cnt | ||
# assert self.min_zs_cnt > 0 | ||
self.max_bs2_rate = max_bs2_rate | ||
assert self.max_bs2_rate <= 1 | ||
self.macd_algo = macd_algo | ||
self.bs1_peak = bs1_peak | ||
self.target_types = bs_type | ||
self.stragety_para = stragety_para | ||
self.bsp2_follow_1 = bsp2_follow_1 | ||
self.bsp3_follow_1 = bsp3_follow_1 | ||
self.bsp2s_follow_2 = bsp2s_follow_2 | ||
self.strict_bsp3 = strict_bsp3 | ||
self.score_thred = score_thred | ||
|
||
def parse_target_type(self): | ||
if type(self.target_types) == str: | ||
self.target_types = [t.strip() for t in self.target_types.split(",")] | ||
for target_t in self.target_types: | ||
assert target_t in ['1', '2', '3', '2s', '1p'] | ||
|
||
def GetStragetyPara(self, k): | ||
return self.stragety_para[k] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
from Bi.CBi import CBi | ||
from common.CEnum import BI_DIR | ||
|
||
|
||
class CBS_Point: | ||
def __init__(self, bi: CBi, is_buy, bs_type, relate_bsp1, extrainfo={}): | ||
self.bi = bi | ||
self.klu = bi.get_end_klu() | ||
self.is_buy = is_buy | ||
self.type = [bs_type] | ||
self.relate_bsp1 = relate_bsp1 | ||
|
||
self.extrainfo = extrainfo | ||
self.update_extrainfo() | ||
|
||
def __str__(self): | ||
return f"{self.klu.time}-{self.type2str()}{'b' if self.is_buy else 's'}" | ||
|
||
def add_type(self, bs_type, extrainfo={}): | ||
self.type.append(bs_type) | ||
self.add_feat(extrainfo) | ||
|
||
def type2str(self): | ||
return ",".join(self.type) | ||
|
||
def has_type(self, x): | ||
return str(x) in self.type | ||
|
||
def qjt_type(self): | ||
return [f"q{x}" for x in self.type] | ||
|
||
def toJson(self): | ||
return { | ||
"bi": self.bi.idx, | ||
"klu": self.klu.toJson(), | ||
"is_buy": self.is_buy, | ||
"type": self.type2str(), | ||
"extrainfo": self.extrainfo, | ||
} | ||
|
||
def add_feat(self, inp1, inp2=None): | ||
if inp2 is None: | ||
assert type(inp1) == dict | ||
self.extrainfo.update(inp1) | ||
else: | ||
self.extrainfo.update({inp1: inp2}) | ||
|
||
def extract_feat(self, prefix): | ||
res = {} | ||
for k, v in self.extrainfo.items(): | ||
if k.startswith(prefix): | ||
res[k] = v | ||
return res | ||
|
||
def update_extrainfo(self): | ||
self.extrainfo.update(self.bi.Get3KZSFeat()) | ||
self.add_feat({ | ||
"bsp_bi_klu_cnt": self.bi.get_end_klu().idx-self.bi.get_begin_klu().idx+1, | ||
"bsp_fx_break": self.bi.get_fx_break_rate(), | ||
}) | ||
last_klu = self.bi.get_last_klu() | ||
if last_klu.boll: | ||
boll = last_klu.boll | ||
c = last_klu.close | ||
self.add_feat({ | ||
"bsp_boll_theta": boll.theta, | ||
"bsp_boll_mid": (c-boll.MID)/boll.MID, | ||
"bsp_boll_up": (c-boll.UP)/boll.UP, | ||
"bsp_boll_down": (c-boll.DOWN)/boll.DOWN, | ||
"bsp_boll_theta_cnt": (c-boll.MID)/boll.theta, # UP和DOWN不重要,可以推导出来的 | ||
}) | ||
self.add_feat( | ||
"bsp_boll_end", | ||
(last_klu.low-boll.DOWN)/boll.DOWN if self.bi.dir == BI_DIR.DOWN else (boll.UP-last_klu.high)/boll.UP, | ||
) | ||
if self.relate_bsp1: | ||
assert self.type2str().find("1") < 0 | ||
self.add_feat(self.relate_bsp1.extract_feat("bsp1_")) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from combiner.CKLine_Combiner import CKLine_Combiner | ||
from common.CEnum import KLINE_DIR, FX_TYPE | ||
|
||
|
||
# 合并后的K线 | ||
class KLine(CKLine_Combiner): | ||
def __init__(self, kl_unit, idx, _dir=KLINE_DIR.UP): | ||
super(KLine, self).__init__(kl_unit, _dir) | ||
self.idx = idx | ||
self.kl_type = kl_unit.kl_type | ||
# 下面是父类成员 | ||
# self.time_begin = kl_unit.time | ||
# self.time_end = kl_unit.time | ||
# self.high = kl_unit.high | ||
# self.low = kl_unit.low | ||
# self.lst = [kl_unit] # 本级别每一根单位K线 | ||
# self.dir = _dir | ||
# self.fx = FX_TYPE.UNKNOWN | ||
# self.pre | ||
# self.next | ||
# 父类方法 | ||
# try_add(self, unit_kl) | ||
# test_combine(self, _kl) | ||
|
||
def __str__(self): | ||
fx_token = "" | ||
if self.fx == FX_TYPE.TOP: | ||
fx_token = "^" | ||
elif self.fx == FX_TYPE.BOTTOM: | ||
fx_token = "_" | ||
return f"{self.idx}th{fx_token}:{self.time_begin}~{self.time_end}({self.kl_type}|{len(self.lst)}) low={self.low} high={self.high}" | ||
|
||
def GetSubKLC(self): | ||
# 可能会出现相邻的两个KLC的子KLC会有重复 | ||
# 因为子KLU合并时正好跨过了父KLC的结束时间边界 | ||
last_klc = None | ||
for klu in self.lst: | ||
for sub_klu in klu.get_children(): | ||
if sub_klu.klc != last_klc: | ||
last_klc = sub_klu.klc | ||
yield sub_klu.klc | ||
|
||
def getOutlinearScore(self): | ||
res = {} | ||
for klu in self: | ||
outliner_dict = klu.getOutlinearScore() | ||
if not res: | ||
res = outliner_dict | ||
else: | ||
for k, v in outliner_dict.items(): | ||
if v >= res[k]: | ||
res[k] = v | ||
return res | ||
|
||
def GetNegPosCnt(self): | ||
# 阴线, 阳线数 | ||
res = {"neg": 0, "pos": 0} | ||
for klu in self: | ||
if klu.close < klu.open: | ||
res["neg"] += 1 | ||
else: | ||
res["pos"] += 1 | ||
res["neg_rate"] = res["neg"]/float(len(self)) | ||
res["pos_rate"] = res["pos"]/float(len(self)) | ||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
from .CKline_Unit import KLine_Unit | ||
from .CKLine import KLine | ||
from common.CEnum import KLINE_DIR | ||
from dataSrc.CommonStockAPI import TRADE_INFO_LST | ||
from Bi.CBiList import CBi_List | ||
from ChanConfig import CChanConfig | ||
from Seg.CSegListChan import CSegListChan | ||
from Seg.CSegConfig import CSeg_Config | ||
from Seg.CSegListDYH import CSeg_List_DYH | ||
from Seg.CSegListDef import CSegListDef | ||
from zs.CZSList import CZS_List | ||
from BuySellPoint.CBSPointList import CBSPointList | ||
from Math.OutlinerDetection import CNormOutlinerDetection | ||
|
||
|
||
def get_seglist_instance(seg_config: CSeg_Config): | ||
if seg_config.seg_algo == "chan": | ||
return CSegListChan(seg_config) | ||
elif seg_config.seg_algo == "1+1": | ||
return CSeg_List_DYH(seg_config) | ||
elif seg_config.seg_algo == "break": | ||
return CSegListDef(seg_config) | ||
else: | ||
raise Exception(f"unsupport seg algoright:{seg_config.seg_algo}") | ||
|
||
|
||
class CKline_List: | ||
def __init__(self, kl_type, conf: CChanConfig): | ||
self.kl_type = kl_type | ||
self.config = conf | ||
self.lst = [] # K线列表,可递归 元素KLine类型 | ||
self.bi_list = CBi_List(bi_conf=conf.bi_conf) | ||
self.seg_list = get_seglist_instance(seg_config=conf.seg_conf) | ||
self.segseg_list = get_seglist_instance(seg_config=conf.seg_conf) | ||
|
||
self.zs_list = CZS_List(zs_config=conf.zs_conf) | ||
self.segzs_list = CZS_List(zs_config=conf.zs_conf) | ||
|
||
self.bs_point_lst = CBSPointList(bs_point_config=conf.bs_point_conf) | ||
|
||
self.metric_model_lst = conf.GetMetricModel() | ||
|
||
od_conf = {"win_width": conf.od_win_width, | ||
"mean_thred": conf.od_mean_thred, | ||
"max_zero_cnt": conf.od_max_zero_cnt, | ||
"skip_zero": conf.od_skip_zero, | ||
} | ||
self.tradeinfo_outlinerdetection_dict = { | ||
metric_name: CNormOutlinerDetection(metric_name, **od_conf) for metric_name in TRADE_INFO_LST | ||
} | ||
|
||
if conf.stragety_cls: | ||
self.stragety_cls = conf.stragety_cls(conf) | ||
else: | ||
self.stragety_cls = None | ||
|
||
def __getitem__(self, n): | ||
if isinstance(n, int): | ||
return self.lst[n] | ||
elif isinstance(n, slice): | ||
return self.lst[n.start:n.stop:n.step] | ||
|
||
def __len__(self): | ||
return len(self.lst) | ||
|
||
def cal_seg_and_zs(self): | ||
cal_seg(self.bi_list, self.seg_list) | ||
self.zs_list.cal_bi_zs(self.bi_list, self.seg_list) | ||
cal_zs_in_seg(self.bi_list, self.seg_list, self.zs_list) # 计算seg的zs_lst,以及中枢的bi_in, bi_out | ||
|
||
cal_seg(self.seg_list, self.segseg_list) | ||
self.segzs_list.cal_bi_zs(self.seg_list, self.segseg_list) | ||
cal_zs_in_seg(self.seg_list, self.segseg_list, self.segzs_list) # 计算segseg的zs_lst,以及中枢的bi_in, bi_out | ||
|
||
self.cal_klc_in_bi() # 计算每一笔里面的 klc列表 | ||
self.figure_bs_point() | ||
|
||
def figure_bs_point(self): | ||
self.bs_point_lst.cal(self.bi_list, self.seg_list) | ||
|
||
def add_single_klu(self, klu: KLine_Unit): | ||
klu.set_metric(self.metric_model_lst) | ||
klu.update_outliner(self.tradeinfo_outlinerdetection_dict) | ||
if len(self.lst) == 0: | ||
self.lst.append(KLine(klu, idx=0)) | ||
else: | ||
_dir = self.lst[-1].try_add(klu) | ||
if _dir != KLINE_DIR.COMBINE: # 不需要合并K线 | ||
self.lst.append(KLine(klu, idx=len(self.lst), _dir=_dir)) | ||
if len(self.lst) >= 3: | ||
self.lst[-2].update_fx(self.lst[-3], self.lst[-1]) | ||
if self.bi_list.update_bi(self.lst[-2], self.lst[-1]): | ||
if self.config.triger_step or (self.stragety_cls is not None and self.stragety_cls.conf.only_judge_last is False): # 回放模式 | ||
self.cal_seg_and_zs() | ||
else: | ||
if self.bi_list.try_add_virtual_bi(self.lst[-1]): | ||
if self.config.triger_step or (self.stragety_cls is not None and self.stragety_cls.conf.only_judge_last is False): # 回放模式 | ||
self.cal_seg_and_zs() | ||
|
||
def klu_iter(self): | ||
for klc in self.lst: | ||
for klu in klc.lst: | ||
yield klu | ||
|
||
def cal_klc_in_bi(self): | ||
for bi in self.bi_list: | ||
bi.klc_lst = self[bi.begin_klc.idx:bi.end_klc.idx+1] | ||
|
||
def toJson(self): | ||
res = { | ||
"bi_list": self.bi_list.toJson(), | ||
"seg_list": self.seg_list.toJson(), | ||
"zs_list": self.zs_list.toJson(), | ||
"bsp_list": self.bs_point_lst.toJson(), | ||
} | ||
if self.stragety_cls: | ||
res.update({"stragety": self.stragety_cls.toJson()}) | ||
return res | ||
|
||
def cal_cbsp_summary(self): | ||
if self.stragety_cls: | ||
self.stragety_cls.summary(self) | ||
|
||
|
||
def cal_seg(bi_list, seg_list): | ||
seg_list.update(bi_list) | ||
# 计算每一笔属于哪个线段 | ||
bi_seg_idx_dict = {} | ||
for seg_idx, seg in enumerate(seg_list): | ||
for i in range(seg.start_bi.idx, seg.end_bi.idx+1): | ||
bi_seg_idx_dict[i] = seg_idx | ||
for bi in bi_list: | ||
bi.seg_idx = bi_seg_idx_dict.get(bi.idx, len(seg_list)) # 找不到的应该都是最后一个线段的 | ||
|
||
|
||
def cal_zs_in_seg(bi_list, seg_list, zs_list): | ||
for seg in seg_list: | ||
seg.clear_zs_lst() | ||
for zs in zs_list: | ||
if zs.is_inside(seg): | ||
seg.add_zs(zs) | ||
assert zs.begin_bi.idx > 0 | ||
zs.bi_in = bi_list[zs.begin_bi.idx-1] | ||
if zs.end_bi.idx+1 < len(bi_list): | ||
zs.bi_out = bi_list[zs.end_bi.idx+1] | ||
zs.bi_lst = [] | ||
for bi in bi_list[zs.begin_bi.idx:zs.end_bi.idx+1]: | ||
zs.bi_lst.append(bi) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from dataSrc.CommonStockAPI import CCommonStockApi, TRADE_INFO_LST | ||
|
||
|
||
class CTradeInfo: | ||
def __init__(self, info: dict): | ||
self.metric = {} | ||
self.od_score = {} | ||
self.od_mean = {} | ||
for metric_name in TRADE_INFO_LST: | ||
self.metric[metric_name] = info.get(metric_name, None) | ||
self.od_score[metric_name] = None | ||
self.od_mean[metric_name] = None | ||
|
||
def __str__(self): | ||
return " ".join([f"{metric_name}:{value}" for metric_name, value in self.metric.items()]) | ||
|
||
def toJson(self): | ||
return { | ||
"metric": self.metric, | ||
"od_score": self.od_score, | ||
} | ||
|
||
def update_od(self, tradeinfo_outlinerdetection_dict: dict) -> None: | ||
for metric_name, model in tradeinfo_outlinerdetection_dict.items(): | ||
self.od_score[metric_name] = model.add(self.metric[metric_name]) | ||
self.od_mean[metric_name] = model.mean | ||
|
||
def getOutlinearScore(self): | ||
return { | ||
"volume_outlinear_score": self.od_score[CCommonStockApi.FIELD_VOLUME], | ||
"turnover_outlinear_score": self.od_score[CCommonStockApi.FIELD_TURNOVER], | ||
"turnover_rate_outlinear_score": self.od_score[CCommonStockApi.FIELD_TURNRATE], | ||
"turnover_rate": self.metric[CCommonStockApi.FIELD_TURNRATE], | ||
} |
Empty file.
Oops, something went wrong.