根据缠论的二买进行的买卖信号交易。用通俗的技术分析就叫做拉升回踩点。
本级别是一周(5天), 次级别是一天 【这个可以修改】
没有去判定中枢或者复杂的走势,或者级别, 这里仅用了最基本的走势形态来进行判断, 我发现止损的设置会大大影响收益。
日后还要加入macd增强判断力。
基本逻辑就是本级别过去一段时间有拉升, 回撤之后, 次级别观察回撤是否结束。卖点反之
代码中应用了二八轮动小市值优化版 v2.0.6的一些函数, 在此表示感谢
#file name chan_II_signal.py
'''
Created on 1 Oct 2016
@author: MetalInvest
'''
from kuanke.user_space_api import *
import config
import pandas as pd
import numpy as np
import datetime
from scipy.signal import argrelextrema
class chan_II_signal():
'''
This class analyze II signal (buy/sell) from Chan theory. A simplified version of II signal,
without any central region analysis
'''
buy_signal_record = {}
recent_prime_level_top= {}
recent_prime_level_change_pct = {}
def __init__(self):
'''
Constructor
'''
pass
def clearDict(self):
# called at end of trading day
#chan_II_signal.recent_prime_level_top = {}
for stock in chan_II_signal.recent_prime_level_top.keys():
if stock not in chan_II_signal.buy_signal_record.keys():
del chan_II_signal.recent_prime_level_top[stock]
def getPeriod(self, stock):
recent_high_datetime, recent_low_datetime = chan_II_signal.recent_prime_level_top[stock]
delta = recent_low_datetime - recent_high_datetime
return delta.days
def check_II_sell_signal(self, dataFrame_s):
sell_signal = False
sell_signal = self.checkInSellPoint(dataFrame_s)
return sell_signal
def check_II_buy_signal(self, dataFrame_p, dataFrame_s, stock):
buy_signal = False
# 1. check we had a primary level of price rise, and fallback followed
isAtPrimeLevel = self.checkPrimeLevelInBuyPoint(dataFrame_p, stock)
# 2. check we have a deficient of momentum in sub level
if isAtPrimeLevel:
buy_signal = self.checkSubLevelInBuyPoint(dataFrame_s, stock)
# 3. check we have a deficient of central region divergence in super level (todo)
return buy_signal
def findMaxMin(self, df):
high = df['high'].values
low = df['low'].values
topIndex = argrelextrema(high, np.greater_equal,order=1)[0]
bottomIndex = argrelextrema(high, np.less_equal,order=1)[0]
return topIndex, bottomIndex, high, low
def checkPrimeLevelInBuyPoint(self, prime_df, stock):
recent_price = prime_df['close'][-1]
# high = self.dataFrame_p['high'].values
# low = self.dataFrame_p['low'].values
# topIndex = argrelextrema(high, np.greater_equal,order=1)
# bottomIndex = argrelextrema(high, np.less_equal,order=1)
topIndex, bottomIndex, high, low = self.findMaxMin(prime_df)
if len(topIndex) < 1 or len(bottomIndex) < 2:
return False
recent_low = low[bottomIndex[-1]]
previous_low = low[bottomIndex[-2]]
recent_high= high[topIndex[-1]]
recent_low_datetime = prime_df['low'].index[bottomIndex[-1]]
previous_low_datetime = prime_df['low'].index[bottomIndex[-2]]
recent_high_datetime = prime_df['high'].index[topIndex[-1]]
if recent_low_datetime < recent_high_datetime or recent_high_datetime < previous_low_datetime:
return False
# determine if we just had a rise followed by fallback at prime level
if recent_high > recent_low and recent_low > previous_low:
# we want to make sure this rise is big enough, and the fallback is legit
if recent_high / previous_low >= config.margin['minimum_advance_margin'] and (recent_high - recent_low) / (recent_high - previous_low) >= config.margin['minimum_fallback_margin']:
# check current price hasn't moved to far from recent low
if recent_price / recent_low < config.margin['minimum_divergence_margin_upper'] and recent_price / recent_low > config.margin['minimum_divergence_margin_lower']:
chan_II_signal.recent_prime_level_top[stock] = (recent_high_datetime, recent_low_datetime)
return True
return False
def checkSubLevelInBuyPoint(self, sub_df, stock):
'''
This method depends on the following fields to be set previously
self.recent_low_datetime = None
self.recent_high_datetime = None
self.previous_low_datetime = None
we need to find if the movement momentum has been depleted from lower level
use CHAN definition, we need to find at least two cenral regions in the sub level
we however can not be very strict here with full central region definition as
this is simplified version
We need 6 local max/min
'''
#recent_price = sub_df['close'][-1]
if stock not in chan_II_signal.recent_prime_level_top or stock in chan_II_signal.buy_signal_record:
return False
recent_high_datetime, recent_low_datetime = chan_II_signal.recent_prime_level_top[stock]
work_df = sub_df.ix[recent_high_datetime:recent_low_datetime]
return self.checkInBuyPoint(work_df, stock)
def checkInBuyPoint(self, df, stock):
# we need to find if the movement momentum has been depleted from lower level
# use strict CHAN definition, we need to find at least two cenral regions in the sub level
topIndex, bottomIndex, high, low = self.findMaxMin(df)
if len(topIndex) < 3 or len(bottomIndex) < 3:
return False
# We use simplified version here at least two sub central regions along the fallback trend
recent_low = low[bottomIndex[-1]]
recent_high= high[topIndex[-1]]
recent_low_idx = bottomIndex[-1]
recent_high_idx = topIndex[-1]
second_low = low[bottomIndex[-2]]
second_high = high[topIndex[-2]]
second_low_idx = bottomIndex[-2]
second_high_idx = topIndex[-2]
third_low = low[bottomIndex[-3]]
third_high = high[topIndex[-3]]
third_low_idx = bottomIndex[-3]
third_high_idx = topIndex[-3]
#recent_price will have to be between the recent_low and recent_high
if recent_high > recent_low and recent_low_idx > recent_high_idx:
recent_ratio = (recent_high - recent_low) / (recent_low_idx - recent_high_idx)
if second_high > second_low and second_low_idx > second_high_idx:
second_ratio = (second_high - second_low) / (second_low_idx - second_high_idx)
if third_high > third_low and third_low_idx > third_high_idx and recent_ratio < second_ratio:
third_ratio = (third_high - third_low) / (third_low_idx - third_high_idx)
if third_ratio > second_ratio:
chan_II_signal.buy_signal_record[stock] = df.index[-1].strftime("%Y-%m-%d %H:%M:%S")
return True
return False
def checkInSellPoint(self, sub_df, stock):
if sub_df.empty or stock not in chan_II_signal.buy_signal_record:
return False
_, past_low_datetime = chan_II_signal.recent_prime_level_top[stock]
# the stock to sell has to be in the buy_signal_record dict
# otherwise we have some problems
work_df = sub_df[sub_df.index > chan_II_signal.buy_signal_record[stock]]
topIndex, bottomIndex, high, low = self.findMaxMin(work_df)
if len(topIndex) < 2 or len(bottomIndex) < 2:
return False
recent_low = low[bottomIndex[-1]]
recent_high= high[topIndex[-1]]
recent_low_idx = bottomIndex[-1]
recent_high_idx = topIndex[-1]
second_low = low[bottomIndex[-2]]
second_high = high[topIndex[-2]]
second_low_idx = bottomIndex[-2]
second_high_idx = topIndex[-2]
second_low_datetime = work_df['low'].index[second_low_idx]
#second_high_datetime = work_df['high'].index[second_high_idx]
# make sure we have past previous time
if second_low_datetime > past_low_datetime:
if recent_high > recent_low and recent_high_idx > recent_low_idx:
recent_ratio = (recent_high - recent_low) / (recent_high_idx - recent_low_idx)
if second_high > second_low and second_high_idx > second_low_idx:
second_ratio = (second_high - second_low) / (second_high_idx - second_low_idx)
if recent_ratio < second_ratio or recent_high < second_high:
del chan_II_signal.buy_signal_record[stock]
return True
return False
#file name config.py
'''
Created on 2 Oct 2016
@author: MetalInvest
'''
stop_loss = dict(
stop_loss_conservative = 0.98,
stop_loss_aggressive = 0.93,
stop_loss_normal = 0.95
)
stop_gain = dict(
stop_gain_conservative = 1.03,
stop_gain_aggressvie = 1.13,
stop_gain_normal = 1.07
)
margin = dict(
minimum_advance_margin = 1.13,
maximum_advacne_margin = 1.21,
minimum_divergence_margin_upper = 1.02,
minimum_divergence_margin_lower = 0.98,
minimum_fallback_margin = 0.3
)
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...