金融数学モデリング - 2022 Greater Bay Area Cup 金融数学モデリングの質問 B (問題解決のアイデアといくつかの Python コード)

目次

I. 概要

2. 質問と解釈

1. コンテストの詳細

 2. コンテストの質問の解釈

3. 問題解決方法

1. 最初の質問

最初の質問コード

 2. 2番目の質問

2 番目の質問の部分コード

3. 3 番目の質問:

3番目の質問のコード

4. 4番目の質問

 3. まとめ


I. 概要

私たちのチームが金融数学モデリングに参加するのはこの大会が初めてです。大会前に 2020 グレーター ベイ エリア カップ A の質問で関連する演習を行ってきましたが、金融数学モデリングの質問にはまだいくつかの問題があります。しかし幸いなことに、7 日間のハードワークの後、私たちはまだ 4 つの質問すべてを完了することができました。コンテストの正式な結果は先月発表されました。私たちのチームは 3 位を獲得しました。個人的には、それはすでに非常に良い結果です (最初は賞を獲得する望みはありません、うーん)。

それでは、これら 4 つの質問を見てみましょう :)

2. 質問と解釈

1. コンテストの詳細

このコンペでは問題Bの難易度は高くなく、全体コンペのタイトルは「マクロ経済循環を踏まえた資産配分戦略の構築」となっています。

以下の図に示すように、質問は合計 4 つあります。

 さらに、質問の作成者は、問題を解決するために必要な関連データ セットも提供しています。データ セット ファイルは、おおよそ次のとおりです。

(付録 1: マクロ経済指標データ (質問 1 および 2))

 (別紙2:主要資産指数のマーケットデータ(質問3、4))

 2. コンテストの質問の解釈

たとえば、4 つの質問は次の 3 つの部分に分割できます。

最初の部分は、マクロ経済データの分析と分類、および将来の経済状況の予測です(質問 1 と 2)。

2つ目は、投資可能な主要な資産指数データをもとに相関分析を行うことです(3つ目の質問)。

第 3 部は第 1 部と第 2 部を組み合わせたもので、第 1 部で今後 5 年間の中国マクロ経済情勢の結論を導き出し、第 2 部で大規模資産指数のデータ相関分析結果を示します。一部はメリルリンチのクロックフレームによって使用されます。 投資のために大規模なカテゴリの資産を組み合わせる方法を決定します。

質問者が提供したデータはすべて使用する必要はなく、個人が使用する数理モデリング手法に従って選別して再利用する必要があることに注意してください。

3. 問題解決方法

1. 最初の質問

トピック分析:第一問では、まず2001年から2021年までの期限範囲を定め、国民経済計算におけるGDPとマクロ経済指標データから銀行および通貨におけるマネーサプライを選択する。指標としてはM2指数を使用する。上記2つの指標を用いることで、メリルリンチの時計枠で区切られた4つの経済状況を計測することができます。

                                (図: メリルリンチのクロックフレーム理論)

適用されるデータとアルゴリズムの式:別表 1 指数成長率の GDP、M2 (広範な通貨供給量)、実際のインフレ率 (年) などの既製のデータに基づいて、GDP および通貨供給量 M2 の成長率を計算します。テーマの制約により、2001 年から 2021 年までの 20 年間のマクロ経済パフォーマンスに関連するデータのみが部門指標として選択されます。

 GDP成長率が10%を超えると高成長、それ以外は低成長、インフレ率が6%を超えると高インフレ、それ以外は低インフレと判断。

したがって、計算後、GDP 成長率とインフレ率が得られます。これら 2 つの指標を通じて、メリルリンチの時計フレームに従って過去 20 年間を分類する Python プログラムを作成します。結果は次の図に示されています。

全年度の分類結果をまとめたところ、2001年から2021年までの景気後退期の年は2002年、2009年、2014年、2017年、回復期の年は2001年、2003年、2004年、2005年、2006年、 2007、2008、2010、2011、2012、2013、2018、2021; スタグフレーションの年: 2015、2016、2019、2020; 過熱段階にあった年はありませんでした。

最初の質問のコード:

def classify(GDP,CPI):
    data1 = pd.DataFrame(GDP)
    data2 = pd.DataFrame(CPI)
    #print(data1.iloc[0,0])
    GDP_speed_up = []
    M_tongbi = []
    tongzhanglv = []
    
    drop = []
    recover = []
    overheat = []
    stagflation =[]
    for i in range(21):
        then_year = data1.iloc[i+1,1]
        ago_year = data1.iloc[i,1]
        zhengzhang = ((then_year - ago_year)/ago_year)*100
        GDP_speed_up.append(zhengzhang)

    for j in range(11,253,12):
        M_tb = data2.iloc[j,6]
        M_tongbi.append(M_tb)
    
    for k in GDP_speed_up:
        for z in M_tongbi:
            tongzhang = z - k
            tongzhanglv.append(tongzhang)
            break
    print(GDP_speed_up)
    print(tongzhanglv)
    year = [2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021]
    for a in range(0,len(GDP_speed_up)):
            if (GDP_speed_up[a]<15 and tongzhanglv[a]<6):
                drop.append(year[a])
                
            elif (GDP_speed_up[a]>15 and tongzhanglv[a]<6):
                recover.append(year[a])
                
            elif (GDP_speed_up[a]>15 and tongzhanglv[a]>6):
                overheat.append(year[a])
                
            else :
                stagflation.append(year[a])
    return drop,recover,overheat,stagflation


def divide(drop_1,recover_1,overhead_1,staflation_1):
    index = pd.date_range('2001','2021')
    print(index)
    

 2. 2番目の質問

トピック分析:最初の質問で計算されたGDP成長率に従って、消費者物価指数CPIを使用して通貨商品のインフレ率を計算し、現在の預金金利(月次)を使用してシミュレーションおよび金利を計算します。今後 5 年間の中国のマクロ経済発展を予測する LSTM アルゴリズムは、1 年をタイム スライスとする時系列スライディング ウィンドウを使用して、今後 5 年間の経済成長、インフレ、金利を予測します。

2 番目の質問では将来のデータを予測する必要があるため、モデリングに LSTM アルゴリズムを使用する必要があります。CNN などの機械学習手法と同様に、数学的アルゴリズムを構築するには、データ前処理、モデル トレーニング、データ予測の 3 つのステップを実行する必要があります。モデルを作成してコードを記述します。

データの前処理:時系列データなのでタイムスタンプを統一する必要がある 観察の結果、1988年以降はどのデータも安定している(欠損値がない)傾向にあることがわかったので、1988年から2021年までのデータは選択されました。また、GDPとインフレ率のデータは毎年12月であるため、時間的な均一性を実現するために、M2マネーサプライデータと人民元要求払預金金利をスライスして毎年12月にデータを抽出します。 。データフレームを 2 次元配列として保存し、この差分変換を実行して、時系列データを教師あり学習セットに変換し、データ セットをトレーニング セットとテスト セットに分割し、MinMaxScaler を使用してデータをスケーリングします。 [-1,1] 収束を高速化します。

モデルの学習(手法の選択):モデルの学習にはメモリアルゴリズムを使用する必要があり、RNN(Recurrent Neural Network、RNN)では順序付けされたデータに対するモデルの学習が実現できますが、これをモデルの学習に使用すると勾配消失の問題が発生します。 , 短期記憶しか実現できません. この問題を解決するために, RNN の派生アルゴリズムである LSTM (Long Short Term, LSTM) を使用します. このアルゴリズムは長期依存情報を学習することができ, 解決に非常に適しています私たちのターゲットとなる問題。

予測:予測に関しては、スライディング ウィンドウ予測を採用しています。

操作結果:

メリルリンチの時計と組み合わせた計算結果に基づいて、今後5年間の中国の経済成長は高成長である一方、インフレと金利は低インフレと低インフレの状況にあることがわかります。中国は今後 5年間で回復段階に入るだろうと判断されている。

2 番目の質問部分コード:

#设置随机种子
numpy.random.seed(7)

df = pd.read_excel('./data/GDP_TZ.xlsx')

df.drop(['tongzhanglv'],axis=1,inplace=True)
df['Date']=pd.to_datetime(df['Date'],format='%Y')
# print(data.head())
df = df.set_index(['Date'], drop=True)
dataframe = pd.DataFrame(df)
# print(dataframe)

dataset = dataframe.values
dataset = dataset.astype("float64")
# print(dataframe.head())
#
#异常值检测
fig = plt.figure(1,figsize=(9,6))
ax = fig.add_subplot(111)
bp = ax.boxplot(dataset)
# print(bp['fliers'][0].get_ydata())
# plt.show()

#需要将数据标准化到0-1
scaler = MinMaxScaler(feature_range=(0,1))
dataset = scaler.fit_transform(dataset)
#分割训练集与测试集
train_size = int(len(dataset)*0.75)
test_size = len(dataset)-train_size

# print(test_size)

train,test = dataset[0:train_size,:],dataset[train_size:len(dataset),:]
trainX,trainY = create_dataset(train,look_back)
testX,testY = create_dataset(test,look_back)
print(trainX)
print(trainY)


#创建一个LSTM模型
model = Sequential()
model.add(LSTM(4,input_shape=(1,look_back)))
model.add(Dense(1))
model.compile(loss='mean_squared_error',optimizer='adam')
trainX= trainX.reshape(trainX.shape[0],1,trainX.shape[1])
# trainY= trainY.reshape(trainY.shape[0],1,trainY.shape[0])
model.fit(trainX,trainY,epochs=100,batch_size=3,verbose=2)

3. 3 番目の質問:

問題分析:付録 2 の主要資産指数のリスク・リターン特性(期待リターン、リターン標準偏差)を計算するには、最初の質問のメリルリンチ時計フレームワークに従って分割された 4 つの経済状態分割条件を使用する必要があります。さまざまな経済状態、シャープレシオ)。ピアソン係数を使用して主要資産インデックス間の相関係数を計算し、ヒート マップを使用して主要資産インデックス間の重要性を表します。

ピアソン係数:

結果を計算し、ヒートマップをプロットします。

(例:不況経済におけるリスクリターン特性)

 (ヒートマップ)

 中国債券総合富裕度(3~5年)と中国債券総合富裕度(7~10年)の相関係数が最も高く計算されており、計算結果から、中国債券総合富裕度(3~5年)間の主要資産指数の相関係数が最も高いことがわかります。同じカテゴリー 異なるカテゴリー間の指数の相関係数よりも高い。

3 番目の質問のコード:

def divide():
    data1 = pd.read_excel(path3)
    data_dalei = pd.DataFrame(data1)
    data_dalei.set_index('time',inplace=True)
    stats = ['stock1','stock2','stock3','stock4','goods1','goods2','bond1','bond2','bond3','cash1']
    data_dalei.reindex(columns=stats)
    return data_dalei
      
def drop(drop_1):
    xiapu = []
    expect_profit = []
    biaozhun = []
    data_dalei = divide()
    for x1 in drop_1:
        data_x_1 = []
        for i in range(6,9):
                data_dalei_drop_2 = data_dalei[str(x1)].iloc[:,i]
            #计算期望收益
                data_expect_profit = data_dalei_drop_2[-1]-data_dalei_drop_2[0]
            #计算夏普比率:
                for i1 in range(1,len(data_dalei_drop_2)):
                    data = ((data_dalei_drop_2[i1]-data_dalei_drop_2[i1-1])/data_dalei_drop_2[i1-1])*100
                    data_x_1.append(data)
                data_x1 = pd.Series(data_x_1)
                sharp = cal_sharp(data_x1,rf = 3)
            #计算收益率标准差
                #平均收益:avg
                qiuhe = 0
                x0 = 0
                for k in range(1,len(data_dalei_drop_2)):
                    data2 = (data_dalei_drop_2[k]-data_dalei_drop_2[k-1])
                    qiuhe = qiuhe + data2
                avg = qiuhe/(len(data_dalei_drop_2)-1)
                #当天收益:then
                for k1 in range(1,len(data_dalei_drop_2)):
                    data3 = (data_dalei_drop_2[k1]-data_dalei_drop_2[k1-1])
                    x = (data3-avg)**2
                    x0 = x0 + x
                biaozhunci = math.sqrt(x0/(len(data_dalei_drop_2)-1))
                xiapu.append(sharp)
                expect_profit.append(data_expect_profit)
                biaozhun.append(biaozhunci)
    M1 = pd.Series(expect_profit)
    M2 = pd.Series(xiapu)
    M3 = pd.Series(biaozhun)
    M4 = pd.concat([M1,M2,M3],axis=1)
    M4.to_excel('./data/dropnew.xlsx')
                
def recover(recover_1):
    xiapu2 = []
    expect_profit2 = []
    biaozhun2 = []
    data_dalei = divide()
    for x2 in recover_1:
        data_x_2 = []
        data_x_3 = []
        data_x= []
        if int(x2) == 2001:
            #计算夏普比率:
            data_dalei_recover = data_dalei[str(x2)].iloc[:,5]
            for i in range(1,len(data_dalei_recover)):
                data = ((data_dalei_recover[i]-data_dalei_recover[i-1])/data_dalei_recover[i-1])*100
                data_x.append(data)
            data_x1 = pd.Series(data_x)
            sharp = cal_sharp(data_x1,rf = 3)
            #计算期望收益:
            data_expect_profit = data_dalei_recover[-1]-data_dalei_recover[0]
            #计算收益率标准差
            qiuhe3 = 0
            x_3 = 0
            for aa in range(1,len(data_dalei_recover)):
                data8 = (data_dalei_recover[aa]-data_dalei_recover[aa-1])
                qiuhe3 = qiuhe3 + data8
            avg3 = qiuhe3/(len(data_dalei_recover)-1)
            for aa1 in range(1,len(data_dalei_recover)):
                data9 = (data_dalei_recover[aa1]-data_dalei_recover[aa-1])
                x_33 = pow(data9-avg3,2)
                x_3 = x_3 +x_33
            zhuanx = x_3/(len(data_dalei_recover))
            biaozhuancha3 = math.sqrt(zhuanx)
            xiapu2.append(sharp)
            expect_profit2.append(data_expect_profit)
            biaozhun2.append(biaozhuancha3)
        elif int(x2) == 2004:
            for kk in range(0,2):
                #计算夏普比率:
                data_dalei_recover = data_dalei[str(x2)].iloc[:,kk]
                for kk1 in range(1,len(data_dalei_recover)):
                    data = ((data_dalei_recover[kk1]-data_dalei_recover[kk1-1])/data_dalei_recover[kk1-1])*100
                    data_x_2.append(data)
                data_x2 = pd.Series(data_x_2)
                sharp1 = cal_sharp(data_x2,rf = 3)
                #计算期望收益:
                data_expect_profit1 = data_dalei_recover[-1]-data_dalei_recover[0]
                #计算收益率标准差
                qiuhe2 = 0
                x_2 = 0
                for kk3 in range(1,len(data_dalei_recover)):
                    datam = (data_dalei_recover[kk3]-data_dalei_recover[kk3-1])
                    qiuhe2 = qiuhe2 +datam
                avg2 = qiuhe2/(len(data_dalei_recover)-1)
                
                for kk4 in range(1,len(data_dalei_recover)):
                    datan = (data_dalei_recover[kk4]-data_dalei_recover[kk4-1])
                    x_22 = pow(datan - avg2,2)
                    x_2 = x_2 + x_22
                biaozhunca = math.sqrt(x_2/len(data_dalei_recover))                
                xiapu2.append(sharp1)
                biaozhun2.append(biaozhunca)
                expect_profit2.append(data_expect_profit1)
        elif int(x2) == 2003:
                #计算夏普比率:
                data_dalei_recover = data_dalei[str(x2)].iloc[:,1]
                for kk1 in range(1,len(data_dalei_recover)):
                    data = ((data_dalei_recover[kk1]-data_dalei_recover[kk1-1])/data_dalei_recover[kk1-1])*100
                    data_x_2.append(data)
                data_x2 = pd.Series(data_x_2)
                sharp1 = cal_sharp(data_x2,rf = 3)
                #计算期望收益:
                data_expect_profit1 = data_dalei_recover[-1]-data_dalei_recover[0]
                #计算收益率标准差
                qiuhe2 = 0
                x_2 = 0
                for kk3 in range(1,len(data_dalei_recover)):
                    datam = (data_dalei_recover[kk3]-data_dalei_recover[kk3-1])
                    qiuhe2 = qiuhe2 +datam
                avg2 = qiuhe2/(len(data_dalei_recover)-1)
                
                for kk4 in range(1,len(data_dalei_recover)):
                    datan = (data_dalei_recover[kk4]-data_dalei_recover[kk4-1])
                    x_22 = pow(datan - avg2,2)
                    x_2 = x_2 + x_22
                biaozhunca = math.sqrt(x_2/len(data_dalei_recover))                
                xiapu2.append(sharp1)
                biaozhun2.append(biaozhunca)
                expect_profit2.append(data_expect_profit1)
        else:
            for kk2 in range(0,4):
                data_dalei_recover_2 = data_dalei[str(x2)].iloc[:,kk2]
            #计算期望收益
                data_expect_profit2 = data_dalei_recover_2[-1]-data_dalei_recover_2[0]
                print(f"期望收益{data_expect_profit2}")
            #计算夏普比率:
                for kk3 in range(1,len(data_dalei_recover_2)):
                    data = ((data_dalei_recover_2[kk3]-data_dalei_recover_2[kk3-1])/data_dalei_recover_2[kk3-1])*100
                    data_x_3.append(data)
                data_x3 = pd.Series(data_x_3)
                sharp2 = cal_sharp(data_x3,rf = 3)
                print(f"夏普:{sharp2}")
            #计算收益率标准差
                #平均收益:avg
                qiuhe1 = 0
                x_1 = 0
                for kk4 in range(1,len(data_dalei_recover_2)):
                    data4 = (data_dalei_recover_2[kk4]-data_dalei_recover_2[kk4-1])
                    qiuhe1 = qiuhe1 + data4
                avg = qiuhe1/(len(data_dalei_recover_2)-1)
                #当天收益:
                for kk5 in range(1,len(data_dalei_recover_2)):
                    data5 = (data_dalei_recover_2[kk5] - data_dalei_recover_2[kk5-1])
                    x_11 = pow(data5-avg,2)
                    x_1 = x_1 + x_11 
                zhuan = x_1/len(data_dalei_recover_2)
                biaozhunci2 = math.sqrt(zhuan)
                print(f"标准差{biaozhunci2}\n")
                qiuhe1 = 0
                x_1 = 0
                x_11=0
                avg = 0
                zhuan = 0
                data5 = 0
                print(f"期望收益{x2}{data_expect_profit2}")
                print(f"夏普:{x2}{sharp2}")
                print(f"收益率标准差{x2}{biaozhunci2}")
                xiapu2.append(sharp2)
                expect_profit2.append(data_expect_profit2)
                biaozhun2.append(biaozhunci2)
    K1 = pd.Series(expect_profit2)
    K2 = pd.Series(xiapu2)
    K3 = pd.Series(biaozhun2)
    K4 = pd.concat([K1,K2,K3],axis=1)
    K4.to_excel('./data/recovernew.xlsx')
      
def overhead(overhead_1):
    data_dalei =  divide()
    for x3 in overhead_1:
        data_dalei_overhear = data_dalei[str(x3)]
    #没有经济过热的年份  
def staflation(staflation_1):
    xiapu3 = []
    expect_profit3 = []
    biaozhun3 = []
    data_dalei = divide()
    for x4 in staflation_1:
        data_x_4 = []
        data_dalei_stagflation = data_dalei[str(x4)].iloc[:,9]
        #计算夏普比率:
        for jj1 in range(1,len(data_dalei_stagflation)):
            data1 = ((data_dalei_stagflation[jj1]-data_dalei_stagflation[jj1-1])/data_dalei_stagflation[jj1-1])*100
            data_x_4.append(data1)
        data_x4 = pd.Series(data_x_4)
        sharp2 = cal_sharp(data_x4,rf = 3)
        
        #计算收益期望:
        data_expect_profit3 = data_dalei_stagflation[-1]-data_dalei_stagflation[0]
        
        #计算收益率标准差:
        qiuhe2 = 0 
        x_2 = 0 
        for jj2 in range(1,len(data_dalei_stagflation)):
            data6 = (data_dalei_stagflation[jj2]-data_dalei_stagflation[jj2-1])
            qiuhe2 = qiuhe2 + data6
        avg2 = qiuhe2/(len(data_dalei_stagflation)-1)
        for jj3 in range(1,len(data_dalei_stagflation)):
            data7 = (data_dalei_stagflation[jj3]-data_dalei_stagflation[jj3-1])
            x_x_1 = pow(data7-avg2,2)
            x_2 = x_2 + x_x_1
        zhuan1 = x_2/len(data_dalei_stagflation)
        boapzhuncha3 =math.sqrt(zhuan1)
        xiapu3.append(sharp2)
        expect_profit3.append(data_expect_profit3)
        biaozhun3.append(boapzhuncha3)
        # print(f"夏普比率{sharp2}")
        # print(f"收益期望{data_expect_profit3}")
        # print(f"收益率标准差{boapzhuncha3}\n")  
    L1 = pd.Series(expect_profit3)
    L2 = pd.Series(xiapu3)
    L3 = pd.Series(biaozhun3)
    L4 = pd.concat([L1,L2,L3],axis=1)
    L4.to_excel('./data/stagflationnew.xlsx') 
               
def cal_sharp(daily_returns: np.ndarray, rf=0, period=252):
    """计算夏普比率:(投资组合期望收益率 - 无风险收益) / 投资组合波动率"""
    Er = daily_returns.sum() / len(daily_returns) - rf / period  # 每日的平均收益 - 每日的无风险收益
    sharp = Er / daily_returns.std() * math.sqrt(period)
    return sharp

def xiangguanxing():
    f = pd.read_excel(path3)
    s = f.corr()
    print(s)
    ax = plt.subplots(1,1)
    ax = sns.heatmap(s,vmax = 1,square=True,annot=True)
    plt.xticks()
    plt.yticks()
    # sns.pairplot(f)
    # # sns.pairplot(s,hue='sepal_width')
    # pd.plotting.scatter_matrix(f,figsize=(12,12),range_padding=0.5)
    plt.show()

4. 4番目の質問

トピック分析:株式4種類、債券3種類、商品指数2種類、金融ファンド1種類の計24種類のコロケーションを整理・組み合わせて、過去5年間のリスク・リターン特性を選択3 番目の質問で得られた相関係数のヒートマップに、今後 5 年間の回復段階により適し、高いリターンをもたらす投資ポートフォリオは、SSE 50、CSI 300、華南商品指数であると予測されます。 、CSI-Comprehensive Wealth(3~5年、7~10年)、マネーマーケットファンド。次に、LSTM アルゴリズムを使用して、投資ポートフォリオのリスクとリターンの特性を予測します (この方法は 2 番目の質問に基づいています)。

(4番目の質問は最初の3つの質問を総合的に応用したものなので、ここでは詳しく説明しません)

予測結果:

(例:CSI 300の今後5年間のリスクリターン特性予測結果)

 3. まとめ

質問 B は主にデータ マイニングとデータ分析の知識を使用します。将来のデータの予測には機械学習の LSTM アルゴリズムが使用されます。LSTM は RNN の優れたバリアント モデルとして、RNN モデルの特性のほとんどを継承し、次の問題を解決します。勾配バックプロパゲーション過程の漸減による勾配消失問題は長期間のデータ保存と入力を実現できるため、スライディングウィンドウアルゴリズムに追加することで将来の長期データの予測に活用できます。

このコンテストは私にとって非常に実りのあるものであり、金融​​データモデリングという馴染みのない分野での学習経験とも言えますが、一般的にコンテストの難易度はそれほど高くなく、コンテストは8日間にわたってたっぷりと行われます。時間も長く、競技経験も良好なので、金融数学の練習ゲームとして非常に適しています。

 

 

 

 

 

 

おすすめ

転載: blog.csdn.net/weixin_52135595/article/details/128659211