[Quantification] Spider web strategy recurrence

spider web strategy

Insert image description here

The strategy comes from "Orient Securities-Spider Web Strategy for Stock Index Futures Trend Trading - Capturing Informed Investor Behavior from Transaction Position Tables-Gao Zijian, Wei Jianrong"

Research report overview

The ranking of clearing members’ trading positions is something that will be published on the exchange’s official website after the close of each trading day. The disclosed information is the trading volume and positions of the top 20 clearing members for each commodity futures contract.

Investors' trading behavior includes expectations for market trends, which are ultimately reflected in changes in trading volume and positions.

Investors are divided into two categories: informed investors and uninformed investors. The former are more firmly inclined to sell or buy on one side when trading, and the trading volume created by unit positions is smaller, while the latter's trading behavior is more repetitive and The trading volume created by unit position is larger.

Since the top 20 members in terms of trading volume, buy order volume, and sell order volume are all different, the clearing members common to the three rankings in the current month's contract transaction position table are selected, and the number is recorded as m (m$<= 20). The remaining trading volume, held buy orders, and held sell orders of the current month's contract after excluding the m clearing members are equivalently regarded as one member unit. In this way, there are n = m + 1 member units. For these n member units, the transaction volume is The volume is 20), the remaining trading volume, held buy order volume, and held sell order volume of the current month's contract after excluding the m settlement members are equivalently regarded as one member unit, so there are n=m+1 member units, for this n member units, the trading volume is20 ) , the remaining trading volume, held buy order volume, and held sell order volume of the current month's contract after excluding the m clearing members are equivalently regarded as one member unit, so there are n=m+1 member unit, for the n member units, the trading volume is V_i, the amount of buying orders held is, and the amount of buying orders held is, the quantity of held buy orders is b_i, the quantity of held sell orders is, the quantity of held sell orders is, the number of open sell orders is s_i, construct statistics, construct statistics, construct a statistic Stat_i=\frac{b_i+s_i}{V_i}. The larger it is, the higher the informed component is. We construct a statistic for the total number of the top 20 member companies. The larger the statistic is, the higher the informed component is. For the top 20 member companies, the statistic is constructed. Total number of 20 member companies to construct statistics, the larger it is, the higher its informed content is. The statistics IF=\frac{OI}{Vol}$ is constructed based on the total volume of the top 20 member companies , where OI is the open interest (the amount of buy orders + the amount of sell orders) , Vol is the trading volume.

Construct the ITS (Informed Trader Sentiment) indicator, calculate the Stat of n member units, select member units whose Stat is greater than IF, and treat the selected member units as informed investors. The number of buy orders held by these selected members is The sum of the open sell orders is B, and the sum of the open sell orders is S, ITS = B − SB + S ITS=\frac{BS}{B+S}ITS=B+SBS

Construct UTS (Uninformed Trader Sentiment) indicator and screen member units whose Stat is less than IF. As uninformed investors, UTS = B − SB + S UTS=\frac{BS}{B+S}UTS=B+SBS

Construct MSD (Market Sentiment Difference) indicator, MSD ≡ ITS − UTS MSD\equiv ITS-UTSMSDITSU TS , describes the difference in the extent to which informed investors and uninformed investors are bullish on the market.

Strategy :

  • ITS>0 buy, close the position at the closing price. Otherwise, sell and close the position at the closing price. (We can close the position the next day).
  • Iterative parameter, ITS > λ \lambdaλ buys, otherwise sells.
  • Traversal parameters, UTS < λ \lambdaλ buys, otherwise sells.
  • MSD> λ \lambda λ buys, otherwise sells.
  • MSD technical indicator, buy when MSD>MA(MSD, n), sell on the contrary.

Position data sorting

There are four points that need to be sorted out for this basic data:

  1. The data of the three major commodity exchanges are unified;
  2. Filter shared members;
  3. Clean data;
  4. Calculate data required for research reports;

Data unification of the three major commodity exchanges

There are currently four commodity futures exchanges: Zhengzhou Commodity Exchange, Shanghai Futures Exchange, Dalian Commodity Exchange, and Guangzhou Futures Exchange. Since Guangzhou Futures Exchange currently only has one type of industrial silicon, it is not included in our statistical scope.

The data of the other three exchanges each have their own characteristics, which we need to unify.

Zhengzhou Commodity Exchange, after 19 years, provided documents in pure English and a combination of Chinese and English. The former gave all contracts, and the latter only had main contracts, because we are not sure whether we use the contracts given by the exchange or not each time. is given, so we filter out the latter:

# 筛选不含中文的文件
def contains_chinese(file_path):
    return any(u'\u4e00' <= char <= u'\u9fff' for char in file_path)
if exchange == 'ZhenZhou':
    futures_hold_folder_path_list = [path for path in futures_hold_folder_path_list if not contains_chinese(path)]

The common problem between SHFE and DCE is that they don’t have time, so:

 _, date_string = os.path.split(os.path.split(path)[0])
temp_df = pd.read_csv(path, encoding='gbk', skiprows=1)
temp_df['交易时间'] = pd.to_datetime(date_string)

Another problem with the last issue is that its original column names are all in English, so they need to be changed to Chinese:

if exchange == 'ShangHai':
    temp_df.rename(columns={
    
    "INSTRUMENTID": "品类",
                        "PARTICIPANTABBR1": "会员简称_总成交量", "PARTICIPANTABBR2": "会员简称_总持买单量",
                        "PARTICIPANTABBR3": "会员简称_总持卖单量",
                        "CJ1": "成交量_总成交量", "CJ2": "成交量_总持买单量", "CJ3": "成交量_总持卖单量",
                        "CJ1_CHG": "增减_总成交量", "CJ2_CHG": "增减_总持买单量", "CJ3_CHG": "增减_总持卖单量", }, inplace=True)

Filter shared members

Because the original data is day-by-day, it can be groupbyclassified directly using the method. In this way, the data within the same trading time can be obtained, and finding intersection characters is to filter out shared member companies:

# 计算每日每个品种的交集字符
def find_intersection_chars(group):
    member_cols = ['会员简称_总成交量', '会员简称_总持买单量', '会员简称_总持卖单量']
    intersection = set(group[member_cols[0]])
    for col in member_cols[1:]:
        intersection = intersection.intersection(set(group[col]))
    return list(intersection)
grouped = temp_df.groupby(["品类", "交易时间"])
for group_name, group_df in grouped:
    intersection_chars = find_intersection_chars(group_df)  # 计算每日每个品种的交集字符

Clean data

The original data are all in str format, that is, numbers in the thousands all have commas. This is the first point; secondly, some contracts are inactive and the top twenty member companies are incomplete, so a null value of '-' will appear. This Null values ​​cannot be added or subtracted, so we replace them with 0, but some of the data are negative numbers, which is equivalent to eliminating other negative symbols. This is also a problem. My solution is to require that the entire value is completely equivalent to '- 'Only do it, otherwise don't do it:

# 批量清理数据
def clean_and_convert(value):
    value = 0 if pd.isna(value) or value == '-' else str(value).replace(',', '')
    return int(float(value))
columns_to_clean = ['成交量_总成交量', '成交量_总持买单量', '成交量_总持卖单量', '增减_总成交量', '增减_总持买单量', '增减_总持卖单量']
group_df = group_df.fillna(0)  # 使用fillna()方法将NaN值替换为0
group_df[columns_to_clean] = group_df[columns_to_clean].applymap(clean_and_convert)  # 清理数据

Calculate data required for research reports

There is more code here. My idea is that the basic data is calculated here, and finally a required data indexed by a specific contract and date is returned. That is, there is only one row of data for a single contract and a single date, such as MA305 in April 2023. Statistics of the top twenty members on the 10th.

Here I first calculate the data required for shared members and non-shared members, and then follow the research report. The method is to create a dictionary and then loop to verify whether there are shared members. If so, add it in, and then calculate the statistics separately, and IF statistics are compared and classified to obtain our demand data.

# 基础数据
a = group_df[group_df['会员简称_总成交量'].isin(intersection_chars)]['成交量_总成交量'].sum()
d = group_df[~group_df['会员简称_总成交量'].isin(intersection_chars)]['成交量_总成交量'].sum()
 # 衍生数据
IF = (h + j) / g
member_data = {
    
    member: {
    
    '成交量_总成交量': 0, '成交量_总持买单量': 0, '成交量_总持卖单量': 0} for member in intersection_chars}  # 创建一个字典来存储交集会员的买单量、卖单量和成交量
for member in intersection_chars:
    member_data[member]['成交量_总成交量'] = group_df.loc[group_df['会员简称_总成交量'] == member, '成交量_总成交量'].sum()
    member_data[member]['成交量_总持买单量'] = group_df.loc[group_df['会员简称_总持买单量'] == member, '成交量_总持买单量'].sum()
    member_data[member]['成交量_总持卖单量'] = group_df.loc[group_df['会员简称_总持卖单量'] == member, '成交量_总持卖单量'].sum()
member_stats = {
    
    member: (data['成交量_总持卖单量'] + data['成交量_总持买单量']) / data['成交量_总成交量'] for member, data in member_data.items()}
filtered_members = {
    
    "greater": [], "less": []}
for member, stats in member_stats.items():
    if stats > IF:
        filtered_members["greater"].append(member)
    else:
        filtered_members["less"].append(member)

All code

# variable
exchange = 'ZhenZhou'  # ZhenZhou, DaLian, ShangHai

def contains_chinese(file_path):
    return any(u'\u4e00' <= char <= u'\u9fff' for char in file_path)

# 计算每日每个品种的交集字符
def find_intersection_chars(group):
    member_cols = ['会员简称_总成交量', '会员简称_总持买单量', '会员简称_总持卖单量']
    intersection = set(group[member_cols[0]])
    for col in member_cols[1:]:
        intersection = intersection.intersection(set(group[col]))
    return list(intersection)

# 批量清理数据
def clean_and_convert(value):
    value = 0 if pd.isna(value) or value == '-' else str(value).replace(',', '')
    return int(float(value))

# read data
futures_hold_folder_path = r'\exchange_%s\*' % exchange
futures_hold_folder_path_list = glob(os.path.join(futures_hold_folder_path, '*'))
if exchange == 'ZhenZhou':
    futures_hold_folder_path_list = [path for path in futures_hold_folder_path_list if not contains_chinese(path)]
    futures_hold_folder_path_list = futures_hold_folder_path_list[2830:]
elif exchange == 'DaLian':
    futures_hold_folder_path_list = futures_hold_folder_path_list[15830:]  # 过滤前面不需要的时间
elif exchange == 'ShangHai':
    futures_hold_folder_path_list = futures_hold_folder_path_list[20830:]  # 过滤前面不需要的时间

result = []
for path in tqdm.tqdm(futures_hold_folder_path_list):
    if exchange == 'ZhenZhou':
        temp_df = pd.read_csv(path, encoding='gbk', parse_dates=['交易时间'], skiprows=1)
        grouped = temp_df.groupby(["品类", "交易时间"])
    else:
        _, date_string = os.path.split(os.path.split(path)[0])
        temp_df = pd.read_csv(path, encoding='gbk', skiprows=1)
        temp_df['交易时间'] = pd.to_datetime(date_string)
        if exchange == 'ShangHai':
            temp_df.rename(columns={
    
    "INSTRUMENTID": "品类",
                             "PARTICIPANTABBR1": "会员简称_总成交量", "PARTICIPANTABBR2": "会员简称_总持买单量",
                             "PARTICIPANTABBR3": "会员简称_总持卖单量",
                             "CJ1": "成交量_总成交量", "CJ2": "成交量_总持买单量", "CJ3": "成交量_总持卖单量",
                             "CJ1_CHG": "增减_总成交量", "CJ2_CHG": "增减_总持买单量", "CJ3_CHG": "增减_总持卖单量", }, inplace=True)
        else:
            temp_df.rename(columns={
    
    "合约代码": "品类",}, inplace=True)
        grouped = temp_df.groupby(["品类", "交易时间"])
    for group_name, group_df in grouped:
        intersection_chars = find_intersection_chars(group_df)  # 计算每日每个品种的交集字符
        columns_to_clean = ['成交量_总成交量', '成交量_总持买单量', '成交量_总持卖单量', '增减_总成交量', '增减_总持买单量', '增减_总持卖单量']
        group_df = group_df.fillna(0)  # 使用fillna()方法将NaN值替换为0
        group_df[columns_to_clean] = group_df[columns_to_clean].applymap(clean_and_convert)  # 清理数据
        # 基础数据
        a = group_df[group_df['会员简称_总成交量'].isin(intersection_chars)]['成交量_总成交量'].sum()
        b = group_df[group_df['会员简称_总持买单量'].isin(intersection_chars)]['成交量_总持买单量'].sum()
        c = group_df[group_df['会员简称_总持卖单量'].isin(intersection_chars)]['成交量_总持卖单量'].sum()
        d = group_df[~group_df['会员简称_总成交量'].isin(intersection_chars)]['成交量_总成交量'].sum()
        e = group_df[~group_df['会员简称_总持买单量'].isin(intersection_chars)]['成交量_总持买单量'].sum()
        f = group_df[~group_df['会员简称_总持卖单量'].isin(intersection_chars)]['成交量_总持卖单量'].sum()
        g = group_df['成交量_总成交量'].sum()
        h = group_df['成交量_总持买单量'].sum()
        j = group_df['成交量_总持卖单量'].sum()
        # 衍生数据
        IF = (h + j) / g
        member_data = {
    
    member: {
    
    '成交量_总成交量': 0, '成交量_总持买单量': 0, '成交量_总持卖单量': 0} for member in intersection_chars}  # 创建一个字典来存储交集会员的买单量、卖单量和成交量
        for member in intersection_chars:
            member_data[member]['成交量_总成交量'] = group_df.loc[group_df['会员简称_总成交量'] == member, '成交量_总成交量'].sum()
            member_data[member]['成交量_总持买单量'] = group_df.loc[group_df['会员简称_总持买单量'] == member, '成交量_总持买单量'].sum()
            member_data[member]['成交量_总持卖单量'] = group_df.loc[group_df['会员简称_总持卖单量'] == member, '成交量_总持卖单量'].sum()
        member_stats = {
    
    member: (data['成交量_总持卖单量'] + data['成交量_总持买单量']) / data['成交量_总成交量'] for member, data in member_data.items()}
        filtered_members = {
    
    "greater": [], "less": []}
        for member, stats in member_stats.items():
            if stats > IF:
                filtered_members["greater"].append(member)
            else:
                filtered_members["less"].append(member)
        filtered_members_total_buy = {
    
    
            "greater": sum(member_data[member]['成交量_总持买单量'] for member in filtered_members["greater"]),
            "less": sum(member_data[member]['成交量_总持买单量'] for member in filtered_members["less"])
        }
        filtered_members_total_sell = {
    
    
            "greater": sum(member_data[member]['成交量_总持卖单量'] for member in filtered_members["greater"]),
            "less": sum(member_data[member]['成交量_总持卖单量'] for member in filtered_members["less"])
        }
        filtered_members_total_volume = {
    
    
            "greater": sum(member_data[member]['成交量_总成交量'] for member in filtered_members["greater"]),
            "less": sum(member_data[member]['成交量_总成交量'] for member in filtered_members["less"])
        }
        # result
        result_dict = {
    
    
            "品类": group_name[0],
            "交易时间": group_name[1],
            "交集字符": intersection_chars,
            "共有会员_总成交量": a,
            "共有会员_总持买单量": b,
            "共有会员_总持卖单量": c,
            "非共有会员_总成交量": d,
            "非共有会员_总持买单量": e,
            "非共有会员_总持卖单量": f,
            "前20会员总成交量": g,
            "前20会员总持买单量": h,
            "前20会员总持卖单量": j,
                          'IF': IF,
                          'ITS_buy': filtered_members_total_buy['greater'], 'ITS_sell': filtered_members_total_sell['greater'], 'ITS_volume': filtered_members_total_volume['greater'], 'UTS_buy': filtered_members_total_buy['less'], 'UTS_sell': filtered_members_total_sell['less'], 'UTS_volume': filtered_members_total_volume['less']
        }
        result.append(result_dict)   # 用字典的形式添加,效率更高

result_df = pd.DataFrame(result)
result = result_df.sort_values(['交易时间', '品类'])
print(result)
result.to_csv(r'exchange/%s_hold.csv' % (exchange), encoding='GBK')

Strategy

The research report only counts those with a statistical number greater than the top twenty members among the total members as informed investors, and those with a lower statistical number among the total members as uninformed investors, but this uninformed investor may be more inclined to Weak informed investors among informed investors, then the comparison between shared members and non-shared members is similar to the comparison between large companies and small companies. Small companies will also have large investors, which may reflect some special circumstances.

Therefore, I constructed another indicator for shared members and non-shared members based on the informed and uninformed information reported in the research:

def cal_spider_holding(df):
    df['知情投资者情绪_共有会员'] = (df['共有会员_总持买单量'] - df['共有会员_总持卖单量']) / (df['共有会员_总持买单量'] + df['共有会员_总持卖单量'])  # ITS,类似
    df['非知情投资者情绪_非共有会员'] = (df['非共有会员_总持买单量'] - df['非共有会员_总持卖单量']) / (df['非共有会员_总持买单量'] + df['非共有会员_总持卖单量'])  # UTS
    df['ITS_Stat'] = (df['ITS_buy'] + df['ITS_sell']) / df['ITS_volume']
    df['UTS_Stat'] = (df['UTS_buy'] + df['UTS_sell']) / df['UTS_volume']
    df['ITS'] = (df['ITS_buy'] - df['ITS_sell']) / (df['ITS_buy'] + df['ITS_sell'])
    df['UTS'] = (df['UTS_buy'] - df['UTS_sell']) / (df['UTS_buy'] + df['UTS_sell'])
    df['市场情绪差异_自创'] = df['知情投资者情绪_共有会员'] - df['非知情投资者情绪_非共有会员']  # MSD
    df['MSD'] = df['ITS'] - df['UTS']  # MSD

    df.fillna(method='ffill', inplace=True)
    return df

In addition, I changed the next day's position in the research report into a trend position, that is, if there is no opposite signal, I will keep holding the previous order.

Result analysis

The position factor can show which types of funds have a greater impact and which types of funds have a smaller impact, as well as which types of funds provide positive guidance and which types of funds provide negative guidance. It can even further explore which types of funds often diverge from fund expectations, etc. . Therefore, the position factor can also be added to the quantitative system as a new factor. Currently, each factor has equal weight, and the weight can be automatically adjusted in the future based on IC and other methods.

The backtesting period is from January 1, 2018 to March 7, 2023.

no parameter strategy

In the following, 1 means positive action and -1 means reverse action. For example, when 1, ITS>0 is long and <0 is short. If it is -1, ITS<0 is short and >0 is long.

Insert image description here

Let’s first understand each definition more precisely. First of all, there is no difference in the construction of statistics for ITS, UTS, informed investor sentiment, and uninformed investor sentiment. They are all the corresponding amount of buy orders minus the amount of sell orders divided by the two. Plus, secondly, the difference in market sentiment is consistent with the construction of MSD, which corresponds to informed minus uninformed.

Then let’s understand each category more precisely:

  • Total members are members who appear on three lists at the same time among the top twenty members. My personal understanding is that it is biased towards large companies, such as CITIC and Yongan, which usually appear on three lists at the same time, because The size is too large;
  • Non-shared members are members who do not appear on the three lists at the same time among the top twenty members. My personal understanding is that they are small companies but have their own tendencies. It may be a large company, but because our statistics are based on They are added together, so there is no preference shown, and the result showing that they are the most neutral may also reflect this;
  • ITS is the sum of the members whose IF statistics are greater than the IF statistics of the contract among the total members, which is what the research report considers as informed investors. I understand that among the total members, the unit position creates smaller trading volume, and the position is firmer than the contract itself. Member, but the effect is similar to that of shared membership;
  • UTS is the sum of the total members whose IF statistics are less than the contract IF statistics. They are the uninformed investors considered by the research report. They are indeed the worst-performing category and have more open and closed positions among large-volume customers. A group of people.

First of all, the overall effect is not good, but individual varieties have certain effects, and the strategies that perform well for each variety are different. For example, MA has a good effect in the reverse direction of ITS, but FG has a good effect in ITS forward direction, so this strategy has no Universal applicability requires more thinking about the logic behind the effectiveness of individual varieties.

The following are strategies and varieties with annualized returns of more than 15%:

for annualized income maximum drawdown annualized return drawdown ratio symbol
[‘ITS’, 1] 0.39 -0.25 1.54 FG
['Informed Investor Sentiment_Total Members', -1] 0.38 -0.42 0.91 MA
['Market sentiment difference_self-created', -1] 0.27 -0.50 0.54 FACING
[‘ITS’, -1] 0.27 -0.50 0.53 MA
['Uninformed Investor Sentiment_Unshared Member', -1] 0.23 -0.21 1.09 RM
[‘MSD’, 1] 0.21 -0.28 0.77 ru
[‘MSD’, 1] 0.21 -0.16 1.25 PK
[‘UTS’, 1] 0.20 -0.28 0.72 lu
[‘ITS’, -1] 0.20 -0.32 0.60 p
['Uninformed Investor Sentiment_Unshared Members', 1] 0.20 -0.62 0.32 FACING
[‘UTS’, -1] 0.19 -0.25 0.76 pg
['Informed Investor Sentiment_Shared Members', 1] 0.19 -0.31 0.62 FG
[‘ITS’, -1] 0.19 -0.34 0.55 on
['Market sentiment difference_self-created', 1] 0.18 -0.42 0.44 FG
[‘MSD’, -1] 0.18 -0.46 0.39 MA
['Uninformed Investor Sentiment_Unshared Member', -1] 0.18 -0.34 0.52 on
[‘ITS’, -1] 0.17 -0.60 0.28 FACING
[‘UTS’, 1] 0.17 -0.50 0.34 ru
['Informed Investor Sentiment_Total Members', -1] 0.16 -0.29 0.56 HEY
['Uninformed Investor Sentiment_Unshared Members', 1] 0.16 -0.18 0.89 lh
[‘ITS’, -1] 0.16 -0.27 0.57 HEY
[‘MSD’, 1] 0.15 -0.20 0.77 l

There are parameter strategies

doing

The correct action is to go long when the parameters are > and short when the parameters are <.

Insert image description here

According to the table, first, the overall effect is indeed better than the parameter-free strategy; second, it can be clearly found that the parameters of the return are left-skewed , indicating the same conclusion as the research report on stock index futures. At the same time, this situation has improved after 10 years. It is still reflected in commodity futures; thirdly, whether it is large-volume companies, or the sum of small-volume companies that occasionally appear on the list, or informed investors and uninformed investors specified in the research report, all are based on their net positions It is better to do the opposite, that is, you can make money by doing the opposite to most people in the market (a reflection of the left skew of the parameters).

The reason for the left skew of the parameters has also been explained in the research report. The top twenty members usually have short positions due to the need for institutional hedging; however, the degree of left skew is greater than that of the stock index futures in the research report. The backtest has more In terms of detailed parameters, the best parameter in the research report -0.06 ranks behind the average drawdown ratio of commodities. The -0.6 effect of commodities is relatively better, which may represent the strong power of industrial hedging in commodity futures.

The following are strategies and varieties with annualized returns of more than 20%. It can be seen that the concentration of each variety is high, that is, the performance of a certain variety in different strategies is similar:

for annualized income maximum drawdown annualized return drawdown ratio symbol
[‘MSD’, -0.3] 0.43 -0.21 2.03 pg
[‘ITS’, 0] 0.39 -0.25 1.54 FG
['Market sentiment difference_self-created', -0.3] 0.27 -0.40 0.67 UR
[‘ITS’, -0.3] 0.25 -0.16 1.60 lu
[‘ITS’, -0.6] 0.25 -0.40 0.64 UR
['Informed Investor Sentiment_Total Members', -0.6] 0.25 -0.40 0.63 UR
[‘UTS’, -0.6] 0.25 -0.40 0.63 UR
['Market sentiment difference_self-created', -0.6] 0.25 -0.40 0.63 UR
['Uninformed investor sentiment_unshared members', -0.6] 0.25 -0.40 0.63 UR
[‘MSD’, -0.3] 0.24 -0.28 0.84 PF
[‘UTS’, -0.3] 0.24 -0.41 0.57 UR
[‘UTS’, -0.3] 0.23 -0.26 0.89 pg
['Uninformed investor sentiment_unshared members', -0.3] 0.23 -0.43 0.53 UR
[‘ITS’, -0.6] 0.22 -0.40 0.54 i
['Informed Investor Sentiment_Total Members', -0.6] 0.22 -0.40 0.54 i
[‘UTS’, -0.6] 0.22 -0.40 0.54 i
['Informed Investor Sentiment_Total Members', -0.3] 0.22 -0.40 0.54 i
['Uninformed investor sentiment_unshared members', -0.6] 0.22 -0.40 0.54 i
['Market sentiment difference_self-created', -0.6] 0.22 -0.40 0.54 i
[‘MSD’, -0.6] 0.22 -0.40 0.54 i
[‘ITS’, -0.3] 0.22 -0.39 0.55 i
[‘UTS’, -0.3] 0.21 -0.40 0.53 i
[‘MSD’, 0] 0.21 -0.28 0.77 ru
['Market sentiment difference_self-created', -0.3] 0.21 -0.22 0.95 eb
['Uninformed investor sentiment_unshared members', -0.3] 0.21 -0.40 0.52 i
['Market sentiment difference_self-created', -0.6] 0.21 -0.29 0.73 HEY
[‘MSD’, 0] 0.21 -0.16 1.25 PK
Do the opposite

The opposite is to go short when the parameters are > and long when the parameters are <.

Insert image description here

It can be clearly found that the parameters of the return are right-skewed, which is consistent with the conclusion obtained from the previous positive strategy.

MSD technical indexing

To average MSD, the specific strategy is: go long when MSD crosses the MSD moving average of the past N days, and go short when it crosses above.

Insert image description here

The parameter plain is not particularly regular, and the 3-day moving average has good returns.

However, the overall effect is not qualitatively improved compared to the aforementioned strategies.

Guess you like

Origin blog.csdn.net/food_for_thought/article/details/135251907