---
# System prepended metadata

title: 最近(2022.08.13)負けてるクロスセクションbotについて

---

# 最近(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()
```
