We will implement the strategy of double gods crossing multiple lines. The stock selection condition of the strategy is that the stock forms double gods on the same day (two trading limits at an interval), the K line crosses the 5, 10, 20 and 30 day moving average at the same time, and the 30 day line is above the 60 day line. The closing price of the daily trading limit is defined as buy_point. The purchase price is the opening price and buy on subsequent dates_ The smaller value of point, the selling profit stop price is buy_point*(1+6.18%), stop loss price is buy_point*(1-16.18%).

Before writing this series of articles, the strategy has not been adjusted for parameters, winning rate statistics and back-test analysis. From the perspective of several stocks currently observed, they all have a good increase. Readers can participate in the realization and optimization together to create a firm offer strategy.

After the three-year cycle back test from 2018 to 2020, the annualized return of the strategy is 41.7% and the maximum pullback is 25.8%.

This paper first calculates the limit factor.

# Main code analysis

Create a new source file named data_center_v3.py, see the end of the text for all contents. v3 mainly involves three changes:

### New calculation limit factor function

def zt(df):

This function is used to calculate the limit factor, where:

- Parameter df is the DataFrame of the expansion factor to be calculated
- The return value is the DataFrame containing the extension factor

Here, the daily closing price is 9.8% higher than the previous day's closing price as the trading limit judgment standard. If the limit rises, the factor is True, otherwise it is False.

df['zt'] = np.where((df['close'].values >= 1.098 * df['preclose'].values), True, False)

The daily limit factor is calculated. Considering that the resumption of rights and the daily limit of gem and sci-tech innovation board are increased by 20%, the daily closing price is increased by 9.8% or more compared with the previous day's closing price as the daily limit.

return df

Returns the DataFrame containing the extension factor

### Add calculation expansion factor

def extend_factor(df):

This function is used to calculate the expansion factor, where:

- Parameter df is the DataFrame of the expansion factor to be calculated
- The return value is the DataFrame containing the extension factor

In v3, only the daily limit factor is calculated, and the calculation of double God and other factors will be added later.

df = df.pipe(zt)

Use pipe to call the function zt to calculate the limit factor

return df

Returns the DataFrame containing the extension factor.

### Modify create data function

def create_data(stock_codes, from_date='1990-12-19', to_date=datetime.date.today().strftime('%Y-%m-%d'), adjustflag='2'): """ Download the daily data of the specified stock within the specified date and calculate the expansion factor :param stock_codes: Stock code of data to be downloaded :param from_date: Daily line start date :param to_date: Daily line end date :param adjustflag: Option 1: Post reinstatement option 2: pre reinstatement option 3: no reinstatement option, default to pre reinstatement option :return: None """ # Download stock cycle for code in stock_codes: print('Downloading{}...'.format(code)) # Log in to BaoStock bs.login() # Download daily data out_df = bs.query_history_k_data_plus(code, g_baostock_data_fields, start_date=from_date, end_date=to_date, frequency='d', adjustflag=adjustflag).get_data() # Logout login bs.logout() # Eliminate stop disk data if out_df.shape[0]: out_df = out_df[(out_df['volume'] != '0') & (out_df['volume'] != '')]

The above contents are the same as v2, which can be used for reference v2 analysis content.

if not out_df.shape[0]: continue

If the data is empty, subsequent filtering and expansion factor calculation will not be performed.

out_df.drop_duplicates(['date'], inplace=True)

In case of duplicate data, add a de re filter.

if out_df.shape[0] < g_available_days_limit: continue

Here, it is set to process only those with more than or equal to g_available_days_limit the stock with the root daily data, if the available daily data is less than g_available_days_limit root, no data will be created to ensure that the expansion factor can be calculated effectively in the future.

At the beginning of the file, we set the global variable:

g_available_days_limit = 250

convert_list = ['open', 'high', 'low', 'close', 'preclose', 'volume', 'amount', 'turn', 'pctChg'] out_df[convert_list] = out_df[convert_list].astype(float)

Convert the related field types into float types. These fields downloaded by BaoStock are str types by default. They need to be converted into float types before they can be used for subsequent indicator calculations.

out_df.reset_index(drop=True, inplace=True)

To reset the index, we need to reset the index to maintain the continuity of the index because we have carried out operations such as de duplication and elimination of stop disk data.

out_df = extend_factor(out_df)

Call function extend_factor calculates the expansion factor.

print(out_df)

Print data creation results. Let's take a look at the print results of Sanmei sh.603379:

date open high ... pcfNcfTTM isST zt 0 2019-04-02 32.652593 32.652593 ... 76.815822 0 True 1 2019-04-03 35.917853 35.917853 ... 84.497404 0 True 2 2019-04-04 39.511735 39.511735 ... 92.952079 0 True 3 2019-04-08 43.462210 43.462210 ... 102.245642 0 True 4 2019-04-09 47.755292 47.755292 ... 97.278109 0 False .. ... ... ... ... ... ... ... 598 2021-09-13 31.580000 33.380000 ... -70.841885 0 False 599 2021-09-14 32.520000 35.000000 ... -71.822773 0 False 600 2021-09-15 33.020000 36.250000 ... -79.015949 0 True 601 2021-09-16 37.900000 38.000000 ... -77.381136 0 False 602 2021-09-17 35.510000 39.050000 ... -85.119250 0 True [603 rows x 18 columns]

The penultimate line and the last line show the daily limit on September 15 and 17, 2021. Take a look at the K-line chart:

It can also be seen that both September 15 and 17, 2021 are the daily limit, and the calculation results are correct.

# Summary

This paper mainly introduces the idea of the strategy to be implemented, completes the calculation of the limit factor, and then continues to introduce the implementation of other factors required by the strategy.

So far, the created data is only used for printing, and storage is not realized. Therefore, as long as the program can run normally, there is no need to wait for the program to run. After all the factors in the subsequent articles are introduced, we will perform multi-threaded calculation and save the results to MySQL.

data_ center_ All codes of v3.py are as follows:

import baostock as bs import datetime import sys import numpy as np # Available daily line quantity constraints g_available_days_limit = 250 # BaoStock daily data field g_baostock_data_fields = 'date,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,peTTM,pbMRQ, psTTM,pcfNcfTTM,isST' def get_stock_codes(date=None): """ Gets the of the specified date A Stock code list If parameter date If it is blank, the date of the last trading day will be returned A Stock code list If parameter date If it is not empty and is a trading day, return date Current day A Stock code list If parameter date If it is not empty but not a trading day, the non trading day information will be printed and the program will exit :param date: date :return: A List of stock codes """ # Log in to biostock bs.login() # Query stock data from BaoStock stock_df = bs.query_all_stock(date).get_data() # If the length of the acquired data is 0, it means that the date is not a trading day if 0 == len(stock_df): # If the parameter date is set, the print message indicates that date is a non trading day if date is not None: print('The currently selected date is a non trading day or there is no trading data, please set it date Is the date of a historical trading day') sys.exit(0) # If the parameter date is not set, the latest trading day will be found from the history. When the length of stock data obtained is not 0, the latest trading day will be found delta = 1 while 0 == len(stock_df): stock_df = bs.query_all_stock(datetime.date.today() - datetime.timedelta(days=delta)).get_data() delta += 1 # Logout login bs.logout() # Through stock data screening, the stock codes of Shanghai Stock Exchange and Shenzhen Stock Exchange are between sh.600000 and sz.39900 stock_df = stock_df[(stock_df['code'] >= 'sh.600000') & (stock_df['code'] < 'sz.399000')] # Return to stock list return stock_df['code'].tolist() def create_data(stock_codes, from_date='1990-12-19', to_date=datetime.date.today().strftime('%Y-%m-%d'), adjustflag='2'): """ Download the daily data of the specified stock within the specified date and calculate the expansion factor :param stock_codes: Stock code of data to be downloaded :param from_date: Daily line start date :param to_date: Daily line end date :param adjustflag: Option 1: Post reinstatement option 2: pre reinstatement option 3: no reinstatement option, default to pre reinstatement option :return: None """ # Download stock cycle for code in stock_codes: print('Downloading{}...'.format(code)) # Log in to BaoStock bs.login() # Download daily data out_df = bs.query_history_k_data_plus(code, g_baostock_data_fields, start_date=from_date, end_date=to_date, frequency='d', adjustflag=adjustflag).get_data() # Logout login bs.logout() # Eliminate stop disk data if out_df.shape[0]: out_df = out_df[(out_df['volume'] != '0') & (out_df['volume'] != '')] # If the data is empty, it is not created if not out_df.shape[0]: continue # Delete duplicate data out_df.drop_duplicates(['date'], inplace=True) # Daily data is less than g_available_days_limit, do not create if out_df.shape[0] < g_available_days_limit: continue # Convert numerical data to float type for subsequent processing convert_list = ['open', 'high', 'low', 'close', 'preclose', 'volume', 'amount', 'turn', 'pctChg'] out_df[convert_list] = out_df[convert_list].astype(float) # Reset index out_df.reset_index(drop=True, inplace=True) # Calculate expansion factor out_df = extend_factor(out_df) print(out_df) def extend_factor(df): """ Calculate expansion factor :param df: Expansion factor to be calculated DataFrame :return: With expansion factor DataFrame """ # Use pipe to calculate the limit factor df = df.pipe(zt) return df def zt(df): """ Calculate the limit factor If the limit rises, the factor is True，Otherwise False The closing price of the current day was 9% higher than the closing price of the previous day.8%And above as the trading judgment standard :param df: Expansion factor to be calculated DataFrame :return: With expansion factor DataFrame """ df['zt'] = np.where((df['close'].values >= 1.098 * df['preclose'].values), True, False) return df if __name__ == '__main__': stock_codes = get_stock_codes() create_data(stock_codes)

Blog content is only used for communication and learning, does not constitute investment suggestions, and is responsible for its own profits and losses!

Personal blog: https://coderx.com.cn/ (priority update)

Welcome to forward and leave messages. Wechat group has been established for learning and communication. Group 1 is full and group 2 has been created. Interested readers please scan the code and add wechat!