# 最近(2022.08.13)負けてるクロスセクションbotについて ## ロジック概要 まず、振り返りとしてこのbotのロジックは * UTC16時時点において、bybitのUSDT先物全銘柄のLS比および現先乖離を取得 * LSが低い銘柄順に1から順位付け * 現物高、先物安の銘柄順に1から順位付け * 二つの順位の合計が低い上位10銘柄をロング、高い下位10銘柄をショート * 先物÷現物<0.9941の銘柄は取引除外(バックテスト上あまり影響はない。でも、現物が異常に高い、つまり現物買い需要から生じた乖離ではなく、ヘッジショートが大幅にかかっている売り圧の大きい銘柄のロングを避けるのが狙い) ## バックテスト結果 ### バックテストプロット ___ ![](https://i.imgur.com/FTcv2yc.png) ___ ### 直近の取引詳細 ``` date symbol ls_rank dev_rank sum_rank pr_ch 5160 2022-08-05 16:00:00 BNXUSDT 7.0 4.0 1.0 -0.020055 5161 2022-08-05 16:00:00 CVXUSDT 16.5 6.0 2.0 0.007141 5162 2022-08-05 16:00:00 AAVEUSDT 19.0 13.0 3.0 0.006604 5163 2022-08-05 16:00:00 LPTUSDT 32.0 1.0 4.0 0.002819 5164 2022-08-05 16:00:00 AGLDUSDT 8.0 34.0 5.0 0.025416 5165 2022-08-05 16:00:00 NEARUSDT 6.0 37.0 6.0 -0.016958 5166 2022-08-05 16:00:00 BNBUSDT 12.0 32.0 7.0 0.008192 5167 2022-08-05 16:00:00 OPUSDT 5.0 41.0 8.0 0.048901 5168 2022-08-05 16:00:00 BALUSDT 43.0 8.0 9.0 0.017955 5169 2022-08-05 16:00:00 APEUSDT 15.0 38.0 10.0 0.003329 5170 2022-08-05 16:00:00 JASMYUSDT 144.0 105.0 145.0 -0.031400 5171 2022-08-05 16:00:00 AKROUSDT 119.0 132.0 146.0 -0.014150 5172 2022-08-05 16:00:00 BELUSDT 115.0 141.0 147.0 -0.031622 5173 2022-08-05 16:00:00 ZILUSDT 121.0 136.0 148.5 -0.066508 5174 2022-08-05 16:00:00 CELOUSDT 114.0 143.0 148.5 -0.021961 5175 2022-08-05 16:00:00 LINAUSDT 153.0 105.0 150.0 -0.008679 5176 2022-08-05 16:00:00 SCRTUSDT 109.0 154.0 151.0 -0.044565 5177 2022-08-05 16:00:00 AUDIOUSDT 128.0 146.0 152.0 -0.026435 5178 2022-08-05 16:00:00 KDAUSDT 135.5 144.0 153.0 -0.067599 5179 2022-08-05 16:00:00 HBARUSDT 154.0 145.0 154.0 -0.048602 date symbol ls_rank dev_rank sum_rank pr_ch 5180 2022-08-06 16:00:00 FLOWUSDT 3.0 2.0 1.0 0.002446 5181 2022-08-06 16:00:00 OPUSDT 5.0 18.0 2.0 -0.037818 5182 2022-08-06 16:00:00 CVXUSDT 22.0 4.0 3.0 -0.023983 5183 2022-08-06 16:00:00 C98USDT 29.0 10.0 4.0 -0.014166 5184 2022-08-06 16:00:00 BNXUSDT 16.0 25.0 5.0 -0.006152 5185 2022-08-06 16:00:00 APEUSDT 9.0 35.0 6.0 -0.030313 5186 2022-08-06 16:00:00 AAVEUSDT 17.0 29.0 7.0 0.003563 5187 2022-08-06 16:00:00 VETUSDT 28.0 19.0 8.0 -0.010909 5188 2022-08-06 16:00:00 BNBUSDT 8.0 43.0 9.0 0.018394 5189 2022-08-06 16:00:00 BITUSDT 45.5 6.0 10.0 -0.007988 5190 2022-08-06 16:00:00 THETAUSDT 127.0 141.0 150.0 -0.048384 5191 2022-08-06 16:00:00 OGNUSDT 149.0 124.0 151.0 0.010505 5192 2022-08-06 16:00:00 SKLUSDT 135.5 139.0 152.0 0.010712 5193 2022-08-06 16:00:00 AKROUSDT 129.5 149.0 153.0 0.004992 5194 2022-08-06 16:00:00 KDAUSDT 151.0 128.0 154.0 0.019767 5195 2022-08-06 16:00:00 WAVESUSDT 144.0 142.0 155.0 0.026019 5196 2022-08-06 16:00:00 HBARUSDT 157.0 132.0 156.0 -0.001400 5197 2022-08-06 16:00:00 RSRUSDT 139.5 158.0 157.0 0.019290 5198 2022-08-06 16:00:00 ALGOUSDT 155.0 151.0 158.0 -0.016981 5199 2022-08-06 16:00:00 BELUSDT 159.0 155.0 159.0 0.013832 date symbol ls_rank dev_rank sum_rank pr_ch 5200 2022-08-07 16:00:00 CREAMUSDT 3.0 5.0 1.0 -0.038845 5201 2022-08-07 16:00:00 LDOUSDT 2.0 21.0 2.0 0.005529 5202 2022-08-07 16:00:00 BNBUSDT 6.0 30.0 3.0 0.007606 5203 2022-08-07 16:00:00 CVXUSDT 27.0 12.0 4.0 0.063582 5204 2022-08-07 16:00:00 TRXUSDT 11.0 32.0 5.0 0.002464 5205 2022-08-07 16:00:00 CVCUSDT 43.0 3.0 6.5 0.001686 5206 2022-08-07 16:00:00 ARUSDT 21.0 25.0 6.5 0.031522 5207 2022-08-07 16:00:00 ROSEUSDT 15.0 36.0 8.0 0.142997 5208 2022-08-07 16:00:00 AVAXUSDT 14.0 38.0 9.0 0.036312 5209 2022-08-07 16:00:00 XCNUSDT 53.0 2.0 10.0 0.022608 5210 2022-08-07 16:00:00 HOTUSDT 121.5 139.0 141.0 -0.007454 5211 2022-08-07 16:00:00 CHRUSDT 144.0 117.0 142.0 -0.051167 5212 2022-08-07 16:00:00 AKROUSDT 116.5 146.0 143.0 -0.005104 5213 2022-08-07 16:00:00 MASKUSDT 127.0 137.0 144.0 0.001310 5214 2022-08-07 16:00:00 REEFUSDT 140.0 125.0 145.0 0.010055 5215 2022-08-07 16:00:00 OCEANUSDT 135.0 132.0 146.0 -0.052405 5216 2022-08-07 16:00:00 BELUSDT 148.0 126.0 147.0 -0.018357 5217 2022-08-07 16:00:00 LINAUSDT 147.0 131.0 148.0 -0.004137 5218 2022-08-07 16:00:00 RSRUSDT 136.0 150.0 149.0 -0.107034 5219 2022-08-07 16:00:00 CEEKUSDT 146.0 147.0 150.0 -0.020863 date symbol ls_rank dev_rank sum_rank pr_ch 5220 2022-08-08 16:00:00 LDOUSDT 10.0 3.0 1.0 -0.125059 5221 2022-08-08 16:00:00 TRXUSDT 14.0 20.0 2.0 -0.001685 5222 2022-08-08 16:00:00 ENSUSDT 16.0 19.0 3.0 -0.065281 5223 2022-08-08 16:00:00 BSVUSDT 29.0 9.0 4.0 -0.058543 5224 2022-08-08 16:00:00 CVCUSDT 36.5 2.0 5.0 -0.059862 5225 2022-08-08 16:00:00 SNXUSDT 31.0 8.0 6.0 -0.076742 5226 2022-08-08 16:00:00 ROSEUSDT 11.0 30.0 7.0 -0.039065 5227 2022-08-08 16:00:00 LUNA2USDT 18.0 29.0 8.0 -0.079230 5228 2022-08-08 16:00:00 OPUSDT 8.0 40.0 9.0 -0.134543 5229 2022-08-08 16:00:00 BNBUSDT 4.0 46.0 10.0 -0.029870 5230 2022-08-08 16:00:00 DASHUSDT 146.0 111.0 143.5 0.027145 5231 2022-08-08 16:00:00 ASTRUSDT 143.0 122.0 145.5 0.095622 5232 2022-08-08 16:00:00 1000BTTUSDT 136.0 129.0 145.5 -0.016536 5233 2022-08-08 16:00:00 ANKRUSDT 131.5 134.0 147.0 0.060162 5234 2022-08-08 16:00:00 DOGEUSDT 134.0 138.0 148.0 0.025589 5235 2022-08-08 16:00:00 AUDIOUSDT 133.0 148.0 149.0 0.007786 5236 2022-08-08 16:00:00 DUSKUSDT 145.0 145.0 150.0 0.029608 5237 2022-08-08 16:00:00 JASMYUSDT 147.0 153.0 151.5 0.065267 5238 2022-08-08 16:00:00 CEEKUSDT 149.0 151.0 151.5 0.045083 5239 2022-08-08 16:00:00 OGNUSDT 151.0 150.0 153.0 0.059886 date symbol ls_rank dev_rank sum_rank pr_ch 5240 2022-08-09 16:00:00 AGLDUSDT 6.0 4.0 1.0 0.055843 5241 2022-08-09 16:00:00 BNXUSDT 4.0 9.0 2.0 0.078822 5242 2022-08-09 16:00:00 BSVUSDT 12.0 18.0 3.0 0.042371 5243 2022-08-09 16:00:00 LPTUSDT 30.0 5.0 4.5 0.065865 5244 2022-08-09 16:00:00 JSTUSDT 22.0 13.0 4.5 0.057518 5245 2022-08-09 16:00:00 COTIUSDT 29.0 10.0 6.0 0.062430 5246 2022-08-09 16:00:00 REQUSDT 25.0 15.0 7.0 0.028056 5247 2022-08-09 16:00:00 FITFIUSDT 7.0 36.0 8.5 0.202348 5248 2022-08-09 16:00:00 SANDUSDT 21.0 22.0 8.5 0.038369 5249 2022-08-09 16:00:00 SNXUSDT 32.0 16.0 10.0 0.062092 5250 2022-08-09 16:00:00 SUSHIUSDT 123.0 102.0 127.0 -0.098264 5251 2022-08-09 16:00:00 C98USDT 98.5 127.0 128.0 -0.039423 5252 2022-08-09 16:00:00 HBARUSDT 136.0 91.0 129.0 -0.061576 5253 2022-08-09 16:00:00 LINAUSDT 129.0 102.0 130.0 -0.044665 5254 2022-08-09 16:00:00 JASMYUSDT 131.0 102.0 131.0 -0.062624 5255 2022-08-09 16:00:00 BICOUSDT 103.0 135.0 132.0 -0.049400 5256 2022-08-09 16:00:00 STXUSDT 105.5 133.0 133.0 -0.030936 5257 2022-08-09 16:00:00 DUSKUSDT 120.0 126.0 134.0 -0.035862 5258 2022-08-09 16:00:00 ASTRUSDT 128.0 119.0 135.0 -0.063102 5259 2022-08-09 16:00:00 CEEKUSDT 134.0 120.0 136.0 -0.017504 ``` ## LSと乖離で分解 原因を探るために、LSの順位だけ、現先乖離の順位だけで試しにバックテスト ### 乖離だけ(先物÷現物<0.9941銘柄除外) ![](https://i.imgur.com/Bosq5KN.png) ### 乖離だけ(先物÷現物<0.9941銘柄込み) ![](https://i.imgur.com/6wz9UDm.png) ### LS比だけ(先物÷現物<0.9941銘柄除外) ![](https://i.imgur.com/zWOHQY6.png) ### LS比だけ(先物÷現物<0.9941銘柄込み) ![](https://i.imgur.com/mkWlQbC.png) ## LSのエッジが消えかけてる? バックテスト上ではLS+乖離の組み合わせよりも乖離単体の方が強くなってしまっている。 LS単体の負けが込んできた6月下旬以前では、組み合わせの方が乖離単体よりもシャープレシオにして0.1以上強かった。 ## 全銘柄のLSとバックテストの傾向 バックテストの結果を見ると、負け気味なのはショート側。 直観として「LSが下がりつつある傾向の時にショートをすると、大口の人のロング傾向に逆らっているから負けやすい」というイメージがある。 そこで、Bybit銘柄全体のショートの傾向を見たいから、単なるBTCのLS比とか、OI比重平均LS比 ```python df["oi_usd"] = df["open_interest"]*df["close"] df["ls_oiw"] = df["oi_usd"]*df["ls"] ls_mean = df["ls_oiw"].sum()/df["oi_usd"].sum() ``` をバックテスト上にプロットしてみて、傾向を見てみる ![](https://i.imgur.com/ms0O2VZ.png) ![](https://i.imgur.com/yoE0x0O.png) --- どちらもBTCの比重が大きいから、グラフに大した形はない。 だからBTCを除いたls_mean、BTCとETHどちらものぞいたls_meanをプロットしてみる。 BTCETH除外 ![](https://i.imgur.com/75CRMe9.png) BTCのみ除外 ![](https://i.imgur.com/7qhaVv9.png) --- ## ショートの制限 BTC単体であれ、BTCとETHを除外したls_meanであれ、直近のショートが負けている時にはLSが低い傾向にあることが分かる。 とりあえず、全銘柄LSbotなわけでBTCとETHを除外したls_meanを採用してみて、適当に > ls_mean < 0.53 のときショートをしない の条件を加えてバックテストしてみる ![](https://i.imgur.com/ayw6eRw.png) まあ当然改善するのは目に見えている。 でもここからは色々なことが考えられて、 * そもそも毎日両建てすることで安定を目指しているのに、片方のポジションをなくす日を設けるのはロジックの根幹から外れてない? * やるにしても閾値は固定0.53なのか、移動平均で取るのがいいのか? * ロングは制限しなくてもいいのか? などなど正直沢山ある。 ## コード ```python= from cProfile import label from multiprocessing import Condition from unittest import result import requests from datetime import datetime from datetime import timedelta import time import numpy as np import matplotlib.pyplot as plt import pandas as pd import gc from sympy import O from tqdm import tqdm from scipy import stats import sys import seaborn as sns from datetime import timedelta from datetime import timezone from tqdm import tqdm import pickle import shap import mglearn import glob from requests import Session import json import math import traceback import ccxt class cate_ls: #Binanceの全銘柄リスト取得 def ftx_binance_common_symbols(self): while True: try: binance_api = requests.get("https://fapi.binance.com/fapi/v1/exchangeInfo").json() binance_df = pd.DataFrame(binance_api["symbols"]) binance_perpdf = binance_df[(binance_df["contractType"]=="PERPETUAL")&(binance_df["quoteAsset"]=="USDT")] #print(binance_perpdf["symbol"]) return list(binance_perpdf["symbol"]) except Exception as e: print(e) time.sleep(5) #bybitの銘柄一覧取得 def bybit_symbols(self): while True: try: api = requests.get(f"https://api.bybit.com/v2/public/tickers").json() df = pd.DataFrame(api["result"]) df["symbol"] = df["symbol"].apply(lambda x: "0" if "21" in x else x)#21期限付き先物の銘柄名を文字列"0"に変える df["symbol"] = df["symbol"].apply(lambda x: "0" if "22" in x else x)#22期限付き先物の銘柄名を文字列"0"に変える df["symbol"] = df["symbol"].apply(lambda x: "0" if "23" in x else x)#23期限付き先物の銘柄名を文字列"0"に変える scli = df["symbol"][df["symbol"] != "0"] #期限付きじゃないやつだけを抽出 #print(scli) scli_usdt = scli.apply(lambda x: x if "USDT" in x else "0") #文字列USDTが入ってないやつは削除 list_usdt = list(scli_usdt[scli_usdt != "0"] ) print(list_usdt) print(len(list_usdt)) return list_usdt except Exception as e: print(e) time.sleep(30) #bybitのapiデータ読んでプレミアム取得、集めてるlsのcsvと結合 def bybit_dev_data(self): #"""#bybitのプレミアムapi取得############################################### df_list00 = [] df_list01 = [] self.symbol_list2 = self.bybit_symbols() #self.symbol_list2 = ["BTCUSDT","ETHUSDT"] mins_periods = 60 #何分足にするか today = datetime.now() max_time_delta = int(pd.to_datetime(today).timestamp())-int(pd.to_datetime("2021-07-01").timestamp())#LSのデータ集め始めた2021-11-01くらいまでapi読み出しを遡る i_max = int(max_time_delta/mins_periods/60/200) for i in tqdm(range(0,i_max)): df_list, df_list2 = [], [] startt = int((pd.to_datetime(today) - i*timedelta(minutes=mins_periods*199)).timestamp()) for sy in self.symbol_list2: while True: try: time.sleep(0.1)#api呼び出し制限対策 future_api = requests.get(f"https://api.bybit.com/public/linear/kline?symbol={sy}&interval={mins_periods}&from={startt}&limit=200").json() future_df = pd.DataFrame(future_api["result"]) df_list.append(future_df) future_api2 = requests.get(f"https://api.bybit.com/public/linear/index-price-kline?symbol={sy}&interval={mins_periods}&from={startt}&limit=200").json() future_df2 = pd.DataFrame(future_api2["result"]) df_list2.append(future_df2) break except Exception as e: print("__", e) print("retry in 15 sec") time.sleep(15) df = pd.concat(df_list) dff = pd.concat(df_list2) df_list00.append(df) df_list01.append(dff) time.sleep(0.01) df = pd.concat(df_list00) dff = pd.concat(df_list01) df.to_pickle("df.pkl") dff.to_pickle("dff.pkl") df = pd.read_pickle("df.pkl") dff = pd.read_pickle("dff.pkl") df["date"] = df["open_time"].apply(lambda x: pd.to_datetime(x,unit="s")) dff["date"] = dff["open_time"].apply(lambda x: pd.to_datetime(x,unit="s")) df = df.sort_values(["date", "symbol"]) dff = dff.sort_values(["date", "symbol"]) df = df.drop_duplicates(subset=["date", "symbol"], keep="last") dff = dff.drop_duplicates(subset=["date", "symbol"], keep="last") df = df.reset_index(drop=True) dff = dff.reset_index(drop=True) df0 = pd.merge(df, dff, on=["symbol", "date"], how='outer', suffixes=['', '_s'], indicator=True) df = df0[["date", "symbol", "open", "high", "low", "close", "close_s"]][df0["_merge"]=="both"].copy() df.sort_values(["date", "symbol"],inplace=True) df["open"] = df["open"].apply(float) df["high"] = df["high"].apply(float) df["low"] = df["low"].apply(float) df["close"] = df["close"].apply(float) df["close_s"] = df["close_s"].apply(float) df.to_pickle("bybit_dev.pkl") #""" #"""#bybitlsのcsvを結合############################################################ csv_list = glob.iglob(f"C:/Database/bybit_ls/*.csv") df_list = [] for f in tqdm(csv_list): dff = pd.read_csv(f,index_col=0) df_list.append(dff) df_all0 = pd.concat(df_list) df_all1 = df_all0.reset_index(drop=True) df_all2 = df_all1.drop_duplicates(subset=["time", "symbol"], keep="last") df = df_all2.reset_index(drop=True) df.fillna(0, inplace=True) df0 = df.rename(columns={"time":"date"}) df0 = df0.sort_values(["date","symbol"]) df0.reset_index(drop=True,inplace=True) df0["date"] = df0["date"].apply(lambda x: pd.to_datetime(x)-timedelta(hours=9))#UTCに変換しておく df0.to_pickle("bybit_ls_1h.pkl") #"""############################################################ #"""#binance_lsのデータ整形 df = pd.read_pickle("C:/Database/binance_integration_data/arranged_data_1h.pkl") df = df[["symbol","date", "longAccount", "tplsal"]].copy() df.rename({"longAccount":"ls_bi"},axis=1,inplace=True) df.to_pickle("binance_1h.pkl") #""" #"""LSとプレミアムを結合 df = pd.read_pickle("bybit_dev.pkl") dff = df[["symbol", "date", "close", "close_s"]].copy() list1 = [] dff["dev"] = (dff["close_s"]/dff["close"]-1)*100 for sy, df in dff.groupby("symbol"):#各銘柄ごとに特徴量作成 df.reset_index(drop=True, inplace=True) df["m_dev"] = dff["dev"].rolling(30).mean() list1.append(df) dff = pd.concat(list1) dff.dropna(inplace=True) dff.reset_index(drop=True, inplace=True) df1 = pd.read_pickle("bybit_ls_1h.pkl") #df11 = df1[["symbol", "date", "close", "buy_ratio"]].copy() df11 = df1.copy() df2 = pd.merge(dff, df11, on=["symbol", "date", "close"]) #時間、銘柄、終値がちゃんと一致してるものを結合(最新の終値確定してないやつはここで弾かれる) dfbi = pd.read_pickle("binance_1h.pkl") df3 = pd.merge(df2, dfbi, on=["symbol","date"]) df4 = pd.merge(dff, dfbi, on=["symbol", "date"]) df2.reset_index(drop=True,inplace=True) df3.reset_index(drop=True,inplace=True) df4.reset_index(drop=True,inplace=True) df2["date"] = df2["date"].apply(lambda x: x + timedelta(hours=1))#1時間足のcloseとlsを使う、dateは開始時間だから1時間足しておく df3["date"] = df3["date"].apply(lambda x: x + timedelta(hours=1)) df4["date"] = df4["date"].apply(lambda x: x + timedelta(hours=1)) df2.rename({"buy_ratio":"ls"},axis=1,inplace=True) df3.rename({"buy_ratio":"ls"},axis=1,inplace=True) df2.to_pickle("bybit_ls_premium_1h.pkl") df3.to_pickle("bin_byb_ls_premium_1h.pkl") df4.to_pickle("bin_ls_premium.pkl") print(df2) print(df3) print(df4) #""" return #クロスセクション2 def all_symbol5(self): df0 = pd.read_pickle("bybit_ls_premium_1h.pkl") df0 = df0[df0["date"].apply(lambda x: x.hour)==16].copy()#16時(日本時間深夜1時にポジション変更) sy_li = list(self.ftx_binance_common_symbols()) #binanceとの共通銘柄抽出 del_li = ["USDCUSDT"] #削除したい銘柄一覧 #df0 = df0[df0["symbol"].apply(lambda x: x in sy_li)] df0 = df0[df0["symbol"].apply(lambda x: x not in del_li)] #削除したい銘柄一覧適応 df0["dev"] = df0["close"]/df0["close_s"] #現先乖離計算 df0 = df0[df0["dev"]>=0.9941].copy() #異常に先物が売られてるやつは除外 df0.reset_index(drop=True,inplace=True) #銘柄ごとに特徴量生成################################################ def features(df): df["pr_ch"] = df["close"].pct_change().shift(-1) df["prch"] = df["close"].pct_change() df["prch"] = df["prch"].apply(abs) df["vola"] = df["prch"].rolling(7).mean() #n日平均ボラティリティ df["dev_diff"] = df["dev"].diff() return df df0 = df0.groupby("symbol").apply(features) df0.dropna(inplace=True) df0.reset_index(drop=True,inplace=True) #ボラに応じたロット数################################################ def lot_ratio(df): std_vola = df["vola"][df["symbol"]=="BTCUSDT"].iloc[0] #BTCUSDTのボラを基準とする df["lot"] = std_vola/df["vola"] #BTCUSDTよりボラが大きければ大きいほどロットが小さくなる return df df0 = df0.groupby("date").apply(lot_ratio) #バックテスト################################################ sort = "sum_rank" #sort = "ls_rank" #sort = "dev_rank" #sort = "dev_diff" symboln = 10 trades = [] trades_df = [] def backtests(df): df["ls_rank"] = df["ls"].rank() df["dev_rank"] = df["dev"].rank() df["sum_rank"] = df["ls_rank"] + df["dev_rank"] df["sum_rank"] = df["sum_rank"].rank() df.sort_values([sort],inplace=True,ascending=True) #ascending=Trueの時、特徴量の小さい順にロング、高い順にショート longs_df = df.head(symboln) shorts_df = df.tail(symboln) #longs_df["pr_ch"] = (longs_df["pr_ch"]-0.0014)*longs_df["lot"] longs_df["pr_ch"] = longs_df["pr_ch"]-0.0014 #shorts_df["pr_ch"] = (-shorts_df["pr_ch"]-0.0014)*shorts_df["lot"] shorts_df["pr_ch"] = -shorts_df["pr_ch"]-0.0014 dic = { "date":longs_df["date"].iloc[0], "long_sys":list(longs_df["symbol"]), "trade_up":longs_df["pr_ch"].sum(), "shorts_sys":list(shorts_df["symbol"]), "trade_down":shorts_df["pr_ch"].sum(), } trades.append(dic) trades_df.append(longs_df) trades_df.append(shorts_df) return df df0 = df0.groupby("date").apply(backtests) df = pd.DataFrame(trades) #毎日のトレードの分析##################################### trades_df = pd.concat(trades_df) trades_df.sort_values(["date","sum_rank"],inplace=True) trades_df.reset_index(drop=True,inplace=True) trades_df = trades_df.tail(100) def results_print(df): print(df) return df trades_df[["date","symbol","ls_rank","dev_rank","sum_rank","pr_ch"]].groupby("date").apply(results_print) #結果整理################################################ df["trade"] = df["trade_up"] + df["trade_down"] df["profit"] = df["trade"].cumsum() df["profit2"] = df["profit"].cummax() df["profit_up"] = df["trade_up"].cumsum() df["profit_down"] = df["trade_down"].cumsum() df.dropna(inplace=True) df.reset_index(drop=True, inplace=True) #df = df[df["date"].apply(lambda x: x<pd.to_datetime("2022-07-25"))].copy() payoff_ratio = df["trade"][df["trade"]>0].mean()/df["trade"][df["trade"]<0].mean() maxdd = (df["profit2"]-df["profit"]).max() trades = df["trade"][df["trade"]!=0] sharp = trades.mean()/trades.std() winratio = len(trades[trades>0])/len(trades) profit = df["trade"].sum() print("###########################") print(f'win ratio : {round(winratio,3)}') print(f'sharp ratio : {round(sharp,3)}') print(f'max drawdown : {round(maxdd,3)}') print(f'payoff ratio : {round(abs(payoff_ratio),3)}') print(f'profit :{round(profit,3)}') print("###########################") fig = plt.figure() ax = fig.add_subplot(111) ax.plot(df["date"], df["profit"],color="black") ax.plot(df["date"], df["profit_down"],color="red") ax.plot(df["date"], df["profit_up"],color="green") ax.text(0.01, 0.99, f'win ratio : {round(winratio,3)}\nsharp ratio : {round(sharp,3)}\nmax drawdown : {round(maxdd,3)}\npayoff ratio : {round(abs(payoff_ratio),3)}\nprofit : {round(profit,3)}', verticalalignment='top', transform=ax.transAxes) ax.grid(which = "major", axis = "x", color = "blue", alpha = 0.5,linestyle = "--", linewidth = 1) ax.grid(which = "major", axis = "y", color = "green", alpha = 0.5,linestyle = "--", linewidth = 1) #print(df[["date","long_sys","shorts_sys"]].tail(30)) plt.show() return if __name__ == "__main__": cl = cate_ls() #cl.bybit_symbols() #cl.bybit_dev_data() #データ集め(始めの一回は必要) cl.all_symbol5() ```