Python stock quantitative trading (5) --- stock price gap

Life is self-reliant, and blessing is self-seeking. All misfortunes, blessings and guilt are in the hands of people, doing good will accumulate blessings, and doing evil will invite misfortunes.

What is the stock price gap

The existence of a gap in the K-line chart refers to a blank interval with no trading between two adjacent K-lines. When there is no overlap between today's lowest price and yesterday's highest price, it is called an upward gap; there is no overlap between today's highest price and yesterday's lowest price, which is called a downward gap.

Theoretically speaking, when there is no good or bad news in the market, the stock price should be flat the next day. However, if there is a good one the day before, then in the call auction that day, most investors will buy at a higher price because It may not be able to buy if it is favorable to peg low prices, thus forming an upward gap to open higher. On the contrary, it is gapped and opened low.

This gap left has a certain reference value for judging the ups and downs of the market outlook. However, it should be noted that if you open high and go low and fall within the highest price of yesterday, the gap is filled. It can only be called a gap high and cannot be called a gap. The gap means that the price of the day has not been reverse-covered.

However, we also need to note that if the gap is small, it may have no reference to the market outlook, and there will also be a gap on the ex-rights and ex-dividend date, which is not of reference. Of course, there are exceptions. For example, BYD has not covered the 50 gap. It is meaningless to look at a single stock data alone. This requires additional attention.

Calculate the gap value

In the previous section, we used Goertek as an example to analyze the parameters of various stocks. Today, we switched to a stock called Muyuan shares, because this stock has directly reached its daily limit of 99 due to the announcement of its performance, and now it has fallen to 82. The gap is obvious.

First, let's get the data of Muyuan shares in the past two months. The specific code is as follows:

df = ak.stock_zh_a_daily(symbol="sz002714", start_date="20201103", end_date="20210118",
                             adjust="qfq")
df.to_excel("牧原股份.xlsx")

Next, we define a function to calculate the gap value, the code is as follows:

def count_gap(cPriceUp, preLow, preHigh, low, high, threshold):
    jump_value = 0
    if (cPriceUp > 0) and (low - preHigh) > threshold:
        # 向上跳空
        jump_value = (low - preHigh) / threshold
    elif (cPriceUp < 0) and (preLow - high) > threshold:
        # 向下跳空
        jump_value = (high - preLow) / threshold
    return jump_value

The meaning of the parameters of the function is as follows:

cPriceUp: increase in closing price

preLow: the lowest price yesterday

preHigh: Yesterday’s highest price

low: lowest price

high: the highest price

threshold: gap threshold

The meaning of this function translated into text is as follows:

(1) Upward gap: When the increase cPriceUp is positive, and today's lowest price (low) minus yesterday's highest price (preHigh) is greater than the gap threshold.

(2) Downward gap: When the increase cPriceUp is negative, and yesterday's lowest price (preLow) minus today's highest price (high) is greater than the gap threshold.

Traverse stock data to obtain gaps

First, we need to customize a threshold for judging whether it meets the gap, the code is as follows:

jump_threshold = df["close"].median() * 0.01

Here define the median of closing price * 0.01 as the threshold.

Then, apply the formula to calculate the parameters in the above method, the specific code is as follows:

jump_threshold = df["close"].median() * 0.01
# 计算涨跌幅
df['changeRatio'] = df["close"].pct_change() * 100
# 增加昨日最低价序列
df["preLow"] = df["low"].shift(1)
# 增加昨日最高价序列
df['preHigh'] = df['high'].shift(1)
# 增加空白列jump
df = df.assign(jump=0)
# 计算所有跳空值
df['jump'] = df.apply(
    lambda row: count_gap(row['changeRatio'], row['preLow'], row['preHigh'], row['low'], row['high'], jump_threshold),
    axis=1)

The comment is very detailed, that is, to get all the gaps of the stock and assign them to the jump column, and the jump without the gap value is assigned the value 0. Here we have all the gaps, and then we need to distinguish whether it is an upward gap or a downward gap.

# 向上跳空
up_jump = df[(df["cPriceUp"] > 0) & df["jump"] > 0]
# 向下跳空
down_jump = df[(df["cPriceUp"] < 0) & df["jump"] < 0]

As shown in the code above, you only need to make judgments based on the concept of upward gaps and the concept of downward gaps above.

Draw gaps

After the above code calculation, we have got the gap. Below, we can draw a K-line chart based on these values ​​and mark the position of the gap. The complete code is as follows:

import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.ticker as ticker
import mpl_finance as mpf

def count_gap(cPriceUp, preLow, preHigh, low, high, threshold):
    jump_value = 0
    if (cPriceUp > 0) and ((low - preHigh) > threshold):
        # 向上跳空
        jump_value = (low - preHigh) / threshold
    elif (cPriceUp < 0) and ((preLow - high) > threshold):
        # 向下跳空
        jump_value = (high - preLow) / threshold
    return jump_value

df = pd.read_excel("牧原股份.xlsx")
df['date'] = pd.to_datetime(df['date'])
df['date'] = df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
jump_threshold = df["close"].median() * 0.01
# 计算涨跌幅
df['cPriceUp'] = df["close"].pct_change() * 100
# 增加昨日最低价序列
df["preLow"] = df["low"].shift(1)
# 增加昨日最高价序列
df['preHigh'] = df['high'].shift(1)
# 增加空白列jump
df = df.assign(jump=0)
# 计算所有跳空值
df['jump'] = df.apply(
    lambda row: count_gap(row['cPriceUp'], row['preLow'], row['preHigh'], row['low'], row['high'], jump_threshold),
    axis=1)
# 向上跳空
up_jump = df[(df["cPriceUp"] > 0) & df["jump"] > 0]
# 向下跳空
down_jump = df[(df["cPriceUp"] < 0) & df["jump"] < 0]
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111)
plt.rcParams['font.sans-serif'] = ['SimHei']
#绘制K线图
mpf.candlestick2_ochl(ax, df["open"], df["close"], df["high"], df["low"], width=0.6, colorup='r',
                          colordown='green',
                          alpha=1.0)
#绘制向下跳空与向上跳空缺口指标
for key, val in df.items():
    for index, today in up_jump.iterrows():
        x_posit = df.index.get_loc(index)
        ax.annotate("{}\n{}".format("向上跳空", today["date"]), xy=(x_posit, today["preHigh"]),
                    xytext=(-30, -up_jump["close"].mean() *0.5), xycoords="data",
                    fontsize=18, textcoords="offset points", arrowprops=dict(arrowstyle="simple", color="r"))
for key, val in df.items():
    for index, today in down_jump.iterrows():
        x_posit = df.index.get_loc(index)
        ax.annotate("{}\n{}".format("向下跳空", today["date"]), xy=(x_posit, today["preLow"]),
                    xytext=(-30, down_jump["close"].mean() *0.5), xycoords="data",
                    fontsize=18, textcoords="offset points", arrowprops=dict(arrowstyle="simple", color="r"))
ax.xaxis.set_major_locator(ticker.MaxNLocator(20))
def format_date(x, pos=None):
    if x < 0 or x > len(df['date']) - 1:
        return ''
    return df['date'][int(x)]

ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')

After the operation, the effect obtained is as shown in the following figure:
Gap chart
We mentioned BYD earlier, and so far, it has not covered the 50 gap. What about such stocks? In fact, it's very simple. You set a filter condition, how much the increase exceeds, and ignore the gap. Generally speaking, like BYD, it will definitely not be able to go back, so if the increase is greater than a certain amount, don't record the gap.

Guess you like

Origin blog.csdn.net/liyuanjinglyj/article/details/112809610