Python {Article115}

ようこそ「Python」へ...

ITエンジニアが仮想通貨の自作自動売買システム(bot)で月収7万円のパッシブインカムを得るには [7] BOTのCsvクラスを作成する

ここではITエンジニアがPythonで仮想通貨の自動売買システム(BOT)を作成してパッシブインカム(Passive Income)を得る方法を解説します。 「仮想通貨のボット(BOT)でパッシブインカムを得る」シリースは以下の11回に分けて解説します。 第7回目ではこのシリーズで作成するBOTのCsvクラスを作成する方法を解説します。 なお、このシリーズで作成するBOTは日本の取引所「GMOコイン」を利用することを前提にしています。 bitFlyer、Binanceなどの取引所を利用するBOTについては後日、別記事にて解説します。

予め断っておきますが、BOTを作成したからといってすぐには稼げるようにはなりません。 3ヶ月から6ヶ月かけて仮想取引とリアル取引をしてBOTのアルゴリズムとパラメータを調整する必要があります。 そうすれば半年後には投資額にもよりますが月5万円から10万円くらいは稼げるようになっているはずです。

半年経っても月10万円稼げないときは次の「座右の銘」を思い出してください。 きっと稼げるようになるはずです。

「上がり始めたら買え(下がっている間は買うな)。 下がり始めたなら売れ(上がっている間は売るな)。 また、そもそも当てられるわけのない天井や底で売買しようとするな。 一番安いところで買ったり、 一番高いところで売れるものだと思うな。」 このシリーズではMicrosoftのVisual Studio Code(VS Code)を使用しますが、Jupyter NotebookなどのツールでもOKです。 説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。

【免責事項】
当記事や当サイトの情報を参考に仮想通貨のBOT(自動トレードプログラム)を動かす場合は、すべて自己責任でお願いいたします。 当サイトの情報を参考にして発生したいかなる損害も責任を負いません。

BOTのCsvクラスを作成する前に、予め以下の「オブジェクト指向プログラミング」のシリーズを読んでクラスの基本を理解してください。

BOTのCsvクラスを作成する

  1. Csvクラスを作成して__init__(), __str__()メソッドを追加する

    ここではCsvクラスを作成して__init__()、__str__()メソッドを追加します。 __init__()メソッドはCsvクラスのインスタンスを生成したときに自動的に呼ばれます。 __str__()メソッドはprint()等でCsvクラスを表示したときに呼ばれます。 __init__()、__str__()の詳しいことは、 「記事(Article085)」、 「記事(Article087)」で詳しく解説しています。

    行41-43ではCsvのプロパティ(Pythonでは属性と呼ぶ)にGvar, Coin, Debugクラスのオブジェクトを保存しています。 行45-47ではCsvのプロパティ「folder_doamin, folder_gmo, folder_trading_type」を設定しています。

    行55ではCsvクラスの各種プロパティを取得して戻り値として返しています。

    csv.py:
    # csv.py
    
    """
    Csv class
    """
    
    # import the libraries
    import os
    import os.path
    import glob
    
    import datetime as dt
    from datetime import timedelta
    
    import numpy as np
    import pandas as pd
    
    from lib.base import Bcolors, Gvar, Coin, Gmo_dataframe   
    from lib.debug import Debug
    
    import warnings
    warnings.simplefilter('ignore')
    
    ########## Csv class
    class Csv:
        """
        csv class: 
            file_exists(), delete_allfiles(), 
            get_gmo_config(), get_gmo_action_config(), get_bot_config()
            get_gmo_master()        
            write_buy_order(), update_buy_order(), get_buy_order(), dump_buy_order_with_header() 
            write_buy_order_sub(), update_buy_order_sub(), get_buy_order_sub(), dump_buy_order_with_header()
            write_buy_order_child(), update_buy_order_child(), get_buy_order_child(), dump_buy_order_child_with_header()     
            write_sell_order(), update_sell_order(), get_sell_order(), dump_sell_order_with_header() 
            write_sell_order_sub(), update_sell_order_sub(), get_sell_order_sub(), dump_sell_order_with_header()
            write_sell_order_child(), update_sell_order_child(), get_sell_order_child(), dump_sell_order_child_with_header()     
            get_order_csv(), update_order_csv_buy(), update_order_csv_sell()
        """
        #######################################################
        def __init__(self, gvar: object, coin: object) -> None:
            self.gvar = gvar                
            self.coin = coin                
            self.debug = Debug(gvar)         
    
            self.folder_domain = f'{self.gvar.domain}/' # desktop-pc/ or note-pc/                   
            self.folder_gmo =  f'{self.gvar.domain}/{self.gvar.exchange}/'  # desktop-pc/bot/                                  
            self.folder_trading_type =  f'{self.gvar.domain}/{self.gvar.exchange}/{self.coin.trade_type}/'
            # desktop-pc/bot/buy_sell/     
            # desktop-pc/bot/sell_buy/         
    
            return
    
        #########################
        def __str__(self) -> str:
            return f"Csv({self.folder_domain=}, {self.folder_gmo=}, {self.folder_trading_type=})"

    click image to zoom!
    図1
    図1はデモプログラムの実行結果です。 ここではCsvクラスのインスタンスを生成してプロパティを表示しています。


  2. Csvクラスにfile_exists()メソッドを追加する

    ここではCsvクラスにfile_exists()メソッドを追加します。 このメソッドの引数1にはファイルのパスを指定います。 CSVファイルにヘッダーが存在するときは引数2に「header=True」を指定します。 ヘッダーが存在しないときは引数2を省略します。

    file_exists()メソッドは引数で指定したファイルがディスク上に存在するかどうかチェックして戻り値として「True, False」を返します。

    ファイルがディスク上に存在するときは「True」、 ファイルがディスク上に存在しないときは「False」を返します。 なお、ファイルが存在しても中身が空なら「False」を返します。

    csv.py:
        ##########################################################
        def file_exists(self, csv_file: str, header=None) -> bool:    # used for no header csv file        
            # desktop-pc/bot/buy_sell/filename.csv  
            # desktop-pc/bot/sell_buy/filename.csv     
              
            if os.path.isfile(csv_file):    # true or false
                try:        
                    if header == None:
                        df = pd.read_csv(csv_file, header=None)
                    else:
                        df = pd.read_csv(csv_file)    
                    return True     # file is not empy
    
                except: # pd.io.common.EmptyDataError 
                    return False    # file is empy          
            else:
                return False        # file not found

    click image to zoom!
    図2
    図2はデモプログラムの実行結果です。 ファイル「master(BTC_JPY).csv」は、ディスク上に存在してかつデータが格納されています。 ファイル「master(ETH_JPY).csv」は、ディスク上に存在しますが中身はヘッダーのみです。 ファイル「master(LTC_JPY).csv」は、ディスク上に存在しますが中身が空です。ヘッダーもありません。 ファイル「master(XRP_JPY).csv」は、ディスク上に存在しません。


  3. Csvクラスにdelete_file_driver(), delete_allfiles()メソッドを追加する

    ここではCsvクラスにdelete_file_driver(), delete_allfiles()メソッドを追加します。 delete_file_driver()は親メソッド、delete_allfiles()は子メソッドです。 これらのメソッドはフォルダ「buy_sell」とフォルダ「sell_buy」内の全てのファイルを削除します。

    csv.py:
        ##################################### delete all files
        def delete_file_driver(self) -> None:              
            ### for folder : buy_sell
            dir = f'{self.folder_gmo}/buy_sell/'    # 'desktop-pc/bot/buy_sell/'    
            # delete_allfiles(dir='desktop-pc/bot/buy_sell/') -> None:  
            self.delete_allfiles(dir) 
    
            ### for folder : sell_buy
            dir = f'{self.folder_gmo}/sell_buy/'    # 'desktop-pc/bot/sell_buy/'           
            # delete_allfiles(dir='desktop-pc/bot/sell_buy/') -> None:  
            self.delete_allfiles(dir) 
    
            return        
        
        ############################################ delete all files
        def delete_allfiles(self, dir: str) -> None:          
            # delete all files
            files = glob.glob(os.path.join(dir, '*.*'))  
            for file in files:
                filename = file.split('\\')[1]
                self.debug.print_log(f".... delete_allfiles({dir}): delete file '{Bcolors.WARNING}{filename}{Bcolors.ENDC}' " )
                os.remove(file)    
    
            return

    click image to zoom!
    図3
    図3はデモプログラムの実行結果です。 フォルダ「buy_sell」と「sell_buy」から全てのファイルが削除されています。


  4. Csvクラスにget_bot_config()メソッドを追加する

    ここではCsvクラスにget_bot_config()メソッドを追加します。 このメソッドはBOTの環境設定ファイル「config.csv」を読み込んで内容をtuple型で返します。 戻り値のtuple型データには「run_mode, close_freq, trade_buysell, trade_sellbuy」が格納されています。 これらの戻り値の使い方については後述します。

    csv.py:
        ################################## get a bot config.csv file
        def get_bot_config(self) -> tuple:  # return (run_mode, close_freq, trade_buysell, trade_sellbuy)            
            config_csv = self.folder_gmo + 'config.csv'       
            # desktop-pc/bot/config.csv     
    
            run_mode = 'stop'   
            close_freq = 1  
            trade_buysell = 'tradeBuySell'
            trade_sellbuy = 'tradeSellBuy'                    
    
            if self.file_exists(config_csv, header=True):    # 'config.csv'
                df = pd.read_csv(config_csv)   
                # config.csv:        
                # ----------------------------------------------------------------------------------
                #  #   Column                             Dtype 
                # ----------------------------------------------------------------------------------
                #  0   run_mode                           object 'run' or 'stop' or 'wait'
                #  1   close_freq                         int64  1-9999
                #  2   trade_buysell                      object 'tradeBuySell' or 'suspendBuySell'
                #  3   trade_sellbuy                      object 'tradeSellBuy' or 'suspendSellBuy'
                # ----------------------------------------------------------------------------------
                run_mode = df.iloc[0,0]         # string => 'run' or 'stop' or 'wait' 
                close_freq = df.iloc[0,1]       # int    => 1,2,3,4,...9999
                trade_buysell = df.iloc[0,2]    # string => 'tradeBuySell' or 'suspendBuySell'    
                trade_sellbuy = df.iloc[0,3]    # string => 'tradeSellBuy' or 'suspendSellBuy'
            else:
                self.debug.print_log(f".... get_bot_config(): file not found {config_csv=} ")        
    
            return (run_mode, close_freq, trade_buysell, trade_sellbuy) # ('run', 9999,'tradeBuySell','tradeSellBuy')  or ('run', 9999,'suspendBuySell','suspendSellBuy')

    click image to zoom!
    図4
    図4はデモプログラムの実行結果です。 config.csvファイルの内容がtuple型で返されています。


  5. Csvクラスにwrite_buy_order()メソッドを追加する

    ここではCsvクラスにwrite_buy_order()メソッドを追加します。 このメソッドは買い注文ファイル「buy_order({symbol}).csv」に新規の買い注文データを追加します。

    行11ではCSVのファイル名を生成しています。 行14ではPandasのto_csv()メソッドで買い注文データをCSVファイルに保存しています。 追加モードで保存するので引数に「mode='a'」を指定しています。 CSVファイルにはヘッダーなしで出力するので「header=None」を指定しています。 また、DataFrameのインデックスは不要なので「index=False」を指定しています。

    csv.py:
        ##################################################################################################################################################################### append buy order into the buy order csv file 
        def write_buy_order(self, buy_time: dt.datetime.utcnow, sell_time: dt.datetime.utcnow, qty: float, price: float, real_qty=0.0, real_price=0.0, real_fee=0.0) -> None: 
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal
    
            log_time = dt.datetime.now()
            # 'buy_time','qty','price','real_qty','real_price','real_fee','sell_time','log_time'
            data = [[buy_time, qty, price, real_qty, real_price, real_fee, sell_time, log_time]]   
            df = pd.DataFrame(data, columns=Gmo_dataframe.BUY_ORDER)  
    
            # append a new record to the buy order csv file 
            csv_file = self.folder_trading_type + f'buy_order({symbol}).csv'    
            # desktop-pc/bot/buy_sell/buy_order(BTC_JPY).csv
            # desktop-pc/bot/sell_buy/buy_order(BTC_JPY).csv
            df.to_csv(csv_file, mode='a', header=False, index=False)    # save a csv file (append mode)        
            self.debug.trace_write(f".... {self.gvar.callers_method_name} write_buy_order({buy_time=:%Y-%m-%d %H:%M:%S}, {qty=:,.{_q_}f}, {price=:,.{_p_}f}, {real_qty=:,.{_q_}f}, {real_price=:,.{_p_}f}): ▶ {df.shape[0]=} ") 
    
            return
    

    click image to zoom!
    図5
    図5はデモプログラムの実行結果です。 ここでは新規の買い注文データを買い注文ファイル「buy_order(BTC_JPY).csv」に追加しています。


  6. Csvクラスにupdate_buy_order()メソッドを追加する

    ここではCsvクラスににupdate_buy_order()メソッドを追加します。 このメソッドは注文ファイル「buy_order({symbol}).csv」に格納されているデータを更新します。 更新するデータは引数1の「buy_time」で指定します。 buy_timeはPrimary Keyです。

    行9ではfile_exists()メソッドでCSVファイルがディスク上に存在するかチェックしています。 行10ではPandasのread_csv()メソッドでCSVファイルをDataFrameに取り込んでいます。 CSVファイルにはヘッダーがないので「header=None」を指定しています。 行11ではDataFrameのカラム名(列名)を変更しています。

    行12-14でDataFrameのデータ型をDateTime型に変更しています。 行16-17ではDataFrameを絞り込んでいます。 行21ではDataFrameのデータを更新しています。 行22ではPandasのto_csv()メソッドでDataFrameをディスク上に保存しています。 CSVファイルにはヘッダーとインデックスなしで保存するので「header=False, index=False」を指定しています。

    csv.py:
        ############################################################################################################ update buy order file (mutiple columns)
        def update_buy_order(self, buy_time: dt.datetime.utcnow, col_name_list: list, col_value_list: list) -> None:    # PK(buy_time)
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal
    
            csv_file = self.folder_trading_type + f'buy_order({symbol}).csv'    
            # desktop-pc/bot/buy_sell/buy_order(BTC_JPY).csv   
            # desktop-pc/bot/sell_buy/buy_order(BTC_JPY).csv     
    
            if self.file_exists(csv_file):    
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.BUY_ORDER
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # utc time (aware)
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # utc time (aware)   
                df['log_time']  = pd.to_datetime(df['log_time'])                # jp time
    
                filter_mask = df['buy_time'] == buy_time                        # PK(buy_time)
                dfx = df[filter_mask]
    
                # found buy order ?
                if dfx.shape[0] > 0:
                    df.loc[filter_mask, col_name_list] = col_value_list         # update 
                    df.to_csv(csv_file, header=False, index=False)              # save a csv file (overwrite mode)  
                    self.debug.trace_write(f".... {self.gvar.callers_method_name} update_buy_order({buy_time=:%Y-%m-%d %H:%M:%S}, {col_name_list=}, {col_value_list=}): ▶ {df[filter_mask].shape[0]=} ")                    
                else: # not found buy order
                    self.debug.print_log(f".... {self.gvar.callers_method_name} update_buy_order({buy_time=:%Y-%m-%d %H:%M:%S}): {Bcolors.FAIL}buy order not found{Bcolors.ENDC} ")            
                    self.debug.sound_alert(3) 
            else:
                self.debug.print_log(f".... {self.gvar.callers_method_name} update_buy_order(): {Bcolors.FAIL}file not found{Bcolors.ENDC} {csv_file=} ")      
    
            return

    click image to zoom!
    図6
    図6はデモプログラムの実行結果です。 ここでは買い注文ファイルの先頭レコードの「real_qty, real_price」を更新しています。 「real_qty, real_price」が「0.0」から「0.02」と「888888」に更新されています。


  7. Csvクラスにget_buy_order()メソッドを追加する

    ここではCsvクラスにget_buy_order()メソッドを追加します。 このメソッドは買い注文のCSVファイル「buy_order({symbol}).csv」をPandasのDataFrameに取り込んで返します。

    行5ではCSVのファイル名を生成しています。 行9ではfile_exists()メソッドでCSVファイルがディスク上に存在するかチェックしています。

    行10-11ではPandasのread_csv()メソッドでCSVファイルをPandasのDataFrameに取り込んでカラム名(列名)を更新しています。 CSVファイルにはヘッダーがないので「header=None」を指定しています。

    行27-29ではDataFrameのデータ型をDateTime型に変更しています。

    csv.py:
        ######################################## load buy order file by coin
        def get_buy_order(self) -> pd.DataFrame:  # return df
            symbol = self.coin.symbol
    
            csv_file = self.folder_trading_type + f'buy_order({symbol}).csv'  
            # desktop-pc/bot/buy_sell/buy_order(BTC_JPY).csv  
            # desktop-pc/bot/sell_buy/buy_order(BTC_JPY).csv      
        
            if self.file_exists(csv_file):                
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.BUY_ORDER 
    
                # buy order file: buy_order(BTC_JPY).csv
                # ----------------------------------------------------------------------------------------------------------
                #  #   Column                    Dtype         
                # ----------------------------------------------------------------------------------------------------------        
                #  0   buy_time                  datetime64[utc]    ★ PK (unique) : copy from the GMO dataframe (time UTC)      
                #  1   qty                       float64       
                #  2   price                     float64          
                #  3   real_qty                  float64            sum(sub_order->real_qty)       
                #  4   real_price                float64            mean(sub_order->real_price)        
                #  5   real_fee                  float64            sum(sub_order->real_fee)                                     
                #  6   sell_time                 datetime64[utc]    => link to sell order       
                #  7   log_time                  datetime64[ns]  
                # ----------------------------------------------------------------------------------------------------------
    
                df['buy_time'] = pd.to_datetime(df['buy_time'], utc=True)       # object => UTC time(aware)
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time(aware)        
                df['log_time'] = pd.to_datetime(df['log_time'])                 # object => ns time (jp time)                           
            else:
                df = pd.DataFrame() # empty dataframe                           
            # end of if self.file_exists(csv_file)
    
            return df

    click image to zoom!
    図7
    図7はデモプログラムの実行結果です。 CSVファイル「buy_order(BTC_JPY).csv」がPandasのDataFrameに取り込まれて返されています。


  8. Csvクラスにdump_buy_order_with_header()メソッドを追加する

    ここではCsvクラスにdump_buy_order_with_header()メソッドを追加します。 このメソッドはCSVファイル「buy_order({symbol}).csv」を読み込んでヘッダー付きにしてCSVファイルに保存します。 CSVファイルをヘッダー付きに保存するとExcelで表示させるときに便利です。

    行5ではCSVのファイル名を生成しています。 行9ではget_buy_order()メソッドでCSVファイルをPandasのDataFrameに取り込んでいます。

    行11ではDataFrameのカラム名「buy_time」を世界標準時間から日本時間に変換して新規カラム名「jp_time」に格納しています。 行12ではPandasのto_csv()メソッドでDataFrameをディスク上に保存しています。 CSVファイルにはヘッダー付きで保存されます。 DataFrameのインデックスは不要なので「index=False」を指定しています。

    csv.py:
        ############################################# dump buy order file by coin
        def dump_buy_order_with_header(self) -> None:
            symbol = self.coin.symbol
    
            csv_file = self.folder_trading_type + f'buy_order({symbol})_header.csv'  
            # desktop-pc/bot/buy_sell/buy_order(BTC_JPY)_header.csv  
            # desktop-pc/bot/sell_buy/buy_order(BTC_JPY)_header.csv 
    
            df = self.get_buy_order()
            if df.shape[0] > 0:
                df['jp_time'] = df['buy_time'].apply(lambda x: x + timedelta(hours=9))  # convert utc to local(jp) time
                df.to_csv(csv_file, index=False)  # save a csv file (overwrite)          
    
            return

    click image to zoom!
    図8-1
    図8-1はデモプログラムの実行結果です。 買い注文ファイルがヘッダー付きで保存されています。


    click image to zoom!
    図8-2
    図8-2はヘッダー付きの買い注文ファイルをExcelで開いている画面です。 カラム「buy_time」の世界標準時間が日本時間に変換されてカラム「jp_time」に格納されています。


  9. Csvクラスの全てを掲載

    
    # csv.py
    
    """
    Csv class
    """
    
    # import the libraries
    import os
    import os.path
    import glob
    
    import datetime as dt
    from datetime import timedelta
    
    import numpy as np
    import pandas as pd
    
    from lib.base import Bcolors, Gvar, Coin, Gmo_dataframe   
    from lib.debug import Debug
    
    import warnings
    warnings.simplefilter('ignore')
    
    ########## Csv class
    class Csv:
        """
        Csv class: 
            file_exists(), delete_allfiles(), 
            get_gmo_config(), get_gmo_action_config(), get_bot_config()
            get_gmo_master()        
            write_buy_order(), update_buy_order(), get_buy_order(), dump_buy_order_with_header() 
            write_buy_order_sub(), update_buy_order_sub(), get_buy_order_sub(), dump_buy_order_with_header()
            write_buy_order_child(), update_buy_order_child(), get_buy_order_child(), dump_buy_order_child_with_header()     
            write_sell_order(), update_sell_order(), get_sell_order(), dump_sell_order_with_header() 
            write_sell_order_sub(), update_sell_order_sub(), get_sell_order_sub(), dump_sell_order_with_header()
            write_sell_order_child(), update_sell_order_child(), get_sell_order_child(), dump_sell_order_child_with_header()     
            get_order_csv(), update_order_csv_buy(), update_order_csv_sell()
        """
        
        ###########################     
        def __init__(self) -> None:
            self.gvar = Gvar()              # Gvar
            self.coin = Coin()              # Coin
            self.debug = Debug(self.gvar)   # dependent class 
    
            self.folder_domain = f'{self.gvar.domain}/' # desktop-pc/ or note-pc/          
            self.folder_gmo =  f'{self.gvar.domain}/{self.gvar.exchange}/'  # desktop-pc/bot/                                
            self.folder_trading_type =  f'{self.gvar.domain}/{self.gvar.exchange}/{self.coin.trade_type}/'
            # desktop-pc/bot/buy_sell/     
            # desktop-pc/bot/sell_buy/    
            return
    
        #######################################################
        def __init__(self, gvar: object, coin: object) -> None:
            self.gvar = gvar                # gvar
            self.coin = coin                # coin
            self.debug = Debug(gvar)        # dependent class 
    
            self.folder_domain = f'{self.gvar.domain}/' # desktop-pc/ or note-pc/                   
            self.folder_gmo =  f'{self.gvar.domain}/{self.gvar.exchange}/'  # desktop-pc/bot/                                  
            self.folder_trading_type =  f'{self.gvar.domain}/{self.gvar.exchange}/{self.coin.trade_type}/'
            # desktop-pc/bot/buy_sell/     
            # desktop-pc/bot/sell_buy/         
    
            return
    
        #########################
        def __str__(self) -> str:
            # return f"Csv({self.folder_domain=}, {self.folder_gmo=}, {self.folder_trading_type=})"  
            return f"Csv({self.gvar=}, {self.coin=}, {self.debug=}, {self.folder_domain=}, {self.folder_gmo=}, {self.folder_trading_type=})"            
        
        ##########################################################
        def file_exists(self, csv_file: str, header=None) -> bool:    # used for no header csv file        
            # desktop-pc/bot/buy_sell/filename.csv  
            # desktop-pc/bot/sell_buy/filename.csv     
              
            if os.path.isfile(csv_file):    # true or false
                try:        
                    if header == None:
                        df = pd.read_csv(csv_file, header=None)
                    else:
                        df = pd.read_csv(csv_file)    
                    return True     # file is not empy
    
                except: # pd.io.common.EmptyDataError: 
                    return False    # file is empy          
            else:
                return False        # file not found        
    
        ##################################### delete all files
        def delete_file_driver(self) -> None:              
            ### for folder : buy_sell
            dir = f'{self.folder_gmo}/buy_sell/'    # 'desktop-pc/bot/buy_sell/'    
            # delete_allfiles(dir='desktop-pc/bot/buy_sell/') -> None:  
            self.delete_allfiles(dir) 
    
            ### for folder : sell_buy
            dir = f'{self.folder_gmo}/sell_buy/'    # 'desktop-pc/bot/sell_buy/'           
            # delete_allfiles(dir='desktop-pc/bot/sell_buy/') -> None:  
            self.delete_allfiles(dir) 
    
            return        
        
        ############################################ delete all files
        def delete_allfiles(self, dir: str) -> None:          
            # delete all files
            files = glob.glob(os.path.join(dir, '*.*'))  
            for file in files:
                filename = file.split('\\')[1]
                self.debug.print_log(f".... delete_allfiles(): delete file '{Bcolors.WARNING}{filename}{Bcolors.ENDC}' " )
                os.remove(file)    
    
            return       
        
        ################################ get a gmo config.csv file
        def get_gmo_config(self) -> str:    # return 'run' or 'stop'      
            config_csv = self.folder_domain + 'config.csv'  # desktop-pc/config.csv     
            run_mode = 'stop'                       
    
            if self.file_exists(config_csv, header=True):    # 'config.csv'
                df = pd.read_csv(config_csv)   
                # config.csv df(run_mode)        
                # ----------------------------------------------------------------
                #  #   Column                             Dtype  
                # ---------------------------------------------------------------- 
                #  0   run_mode                           object 'run' or 'stop'                                        
                # ----------------------------------------------------------------
                run_mode = df.iloc[0,0] # 'run' or 'stop'
                return run_mode    
            else:
                self.debug.print_log(f".... get_gmo_config(): file not found {config_csv=} ")       
                self.debug.sound_alert(1) 
                return 'stop'                  
    
        #################################################### get a gmo action_buysell.csv or action_sellbuy.csv file 
        def get_gmo_action_config(self, file: str) -> tuple: # return (act12, act13, act14,...)           
            config_csv = self.folder_domain + file # 'action_buysell.csv' or 'action_sellbuy.csv'       
            # desktop-pc/action_buysell.csv     
            # desktop-pc/action_sellbuy.csv   
    
            if self.file_exists(config_csv, header=True):    # 'action_buysell.csv' or 'action_sellbuy.csv'
                df = pd.read_csv(config_csv)   
                # action_buysell.csv df(act12,act13,...)      
                # action_sellbuy.csv df(act12,act13,...)     
                # -------------------------------------------------------------------
                #  #   Column                             Dtype 
                # ------------------------------------------------------------------- 
                #  0   act12                              bool  True or False      
                #  1   act13                              bool  True or False 
                #  2   act14                              bool  True or False  
                #  3   act15                              bool  True or False                        
                #  4   act21                              bool  True or False 
                #  5   act22                              bool  True or False 
                #  6   act23                              bool  True or False 
                #  7   act24                              bool  True or False 
                #  8   act25                              bool  True or False 
                #  9   act26                              bool  True or False                                       
                # 10   act32_1                            bool  True or False 
                # 11   act32_2                            bool  True or False       
                # 12   act33_1                            bool  True or False 
                # 13   act33_2                            bool  True or False                
                # 14   act41                              bool  True or False                                                                         
                # -------------------------------------------------------------------
                act12   = df.iloc[0,0]    
                act13   = df.iloc[0,1]  
                act14   = df.iloc[0,2]     
                act15   = df.iloc[0,3]                      
                act21   = df.iloc[0,4]  
                act22   = df.iloc[0,5]  
                act23   = df.iloc[0,6]  
                act24   = df.iloc[0,7]  
                act25   = df.iloc[0,8]  
                act26   = df.iloc[0,9]                                      
                act32_1 = df.iloc[0,10]  
                act32_2 = df.iloc[0,11]  
                act33_1 = df.iloc[0,12]  
                act33_2 = df.iloc[0,13]              
                act41   = df.iloc[0,14]  
                return (act12, act13, act14, act15, act21, act22, act23, act24, act25, act26, act32_1, act32_2, act33_1, act33_2, act41)
            else:
                self.debug.print_log(f".... get_gmo_action_config(): file not found {config_csv=} ")      
                #       act12, act13, act14, act15, act21, act22, act23, act24, act25, act26,act32_1,act32_2,act33_1,act33_2,act41  
                return (False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)                     
        
        ################################## get a bot config.csv file
        def get_bot_config(self) -> tuple:  # return (run_mode, close_freq, trade_buysell, trade_sellbuy)            
            config_csv = self.folder_gmo + 'config.csv'       
            # desktop-pc/bot/config.csv     
    
            run_mode = 'stop'   
            close_freq = 1  # 1,2,3,4,...   
            trade_buysell = 'tradeBuySell'
            trade_sellbuy = 'tradeSellBuy'                    
    
            if self.file_exists(config_csv, header=True):    # 'config.csv'
                df = pd.read_csv(config_csv)   
                # config.csv:        
                # -----------------------------------------------------------------------------------------------
                #  #   Column                             Dtype 
                # ----------------------------------------------------------------------------------------------- 
                #  0   run_mode                           object 'run' or 'stop' or 'wait'
                #  1   close_freq                         int64  1-9999
                #  2   trade_buysell                      object 'tradeBuySell' or 'suspendBuySell'
                #  3   trade_sellbuy                      object 'tradeSellBuy' or 'suspendSellBuy'
                # -----------------------------------------------------------------------------------------------
                run_mode = df.iloc[0,0]         # string => 'run' or 'stop' or 'wait' 
                close_freq = df.iloc[0,1]       # int    => 1,2,3,4,...9999
                trade_buysell = df.iloc[0,2]    # string => 'tradeBuySell' or 'suspendBuySell'    
                trade_sellbuy = df.iloc[0,3]    # string => 'tradeSellBuy' or 'suspendSellBuy'
            else:
                self.debug.print_log(f".... get_bot_config(): file not found {config_csv=} ")        
    
            return (run_mode, close_freq, trade_buysell, trade_sellbuy) # ('run', 9999,'tradeBuySell','tradeSellBuy')  or ('run', 9999,'suspendBuySell','suspendSellBuy')    
        
        ##################################################################################################################################################################### append buy order log into the buy order log file 
        def write_buy_order(self, buy_time: dt.datetime.utcnow, sell_time: dt.datetime.utcnow, qty: float, price: float, real_qty=0.0, real_price=0.0, real_fee=0.0) -> None: 
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal
    
            log_time = dt.datetime.now()
            # 'buy_time','qty','price','real_qty','real_price','real_fee','sell_time','log_time'
            data = [[buy_time, qty, price, real_qty, real_price, real_fee, sell_time, log_time]]   
            df = pd.DataFrame(data, columns=Gmo_dataframe.BUY_ORDER)  
    
            # append a new record to the buy order csv file 
            csv_file = self.folder_trading_type + f'buy_order({symbol}).csv'    
            # desktop-pc/bot/buy_sell/buy_order(BTC_JPY).csv
            # desktop-pc/bot/sell_buy/buy_order(BTC_JPY).csv
            df.to_csv(csv_file, mode='a', header=False, index=False)    # append mode        
            self.debug.trace_write(f".... {self.gvar.callers_method_name} write_buy_order({buy_time=:%Y-%m-%d %H:%M:%S}, {qty=:,.{_q_}f}, {price=:,.{_p_}f}, {real_qty=:,.{_q_}f}, {real_price=:,.{_p_}f}): ▶ {df.shape[0]=} ")        
    
            return                
                                 
        ############################################################################################################ update buy order file (mutiple columns)
        def update_buy_order(self, buy_time: dt.datetime.utcnow, col_name_list: list, col_value_list: list) -> None:    # PK(buy_time)
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal
    
            csv_file = self.folder_trading_type + f'buy_order({symbol}).csv'    
            # desktop-pc/bot/buy_sell/buy_order(BTC_JPY).csv   
            # desktop-pc/bot/sell_buy/buy_order(BTC_JPY).csv     
    
            if self.file_exists(csv_file):    
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.BUY_ORDER
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # utc time (aware)
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # utc time (aware)   
                df['log_time']  = pd.to_datetime(df['log_time'])                # jp time
    
                filter_mask = df['buy_time'] == buy_time                        # PK(buy_time)
                dfx = df[filter_mask]
    
                # found buy order ?
                if dfx.shape[0] > 0:
                    df.loc[filter_mask, col_name_list] = col_value_list         # update 
                    df.to_csv(csv_file, header=False, index=False)              # save a csv file (overwrite mode)  
                    self.debug.trace_write(f".... {self.gvar.callers_method_name} update_buy_order({buy_time=:%Y-%m-%d %H:%M:%S}, {col_name_list=}, {col_value_list=}): ▶ {df[filter_mask].shape[0]=} ")                    
                else: # not found buy order
                    self.debug.print_log(f".... {self.gvar.callers_method_name} update_buy_order({buy_time=:%Y-%m-%d %H:%M:%S}): {Bcolors.FAIL}buy order not found{Bcolors.ENDC} ")            
                    self.debug.sound_alert(3) 
            else:
                self.debug.print_log(f".... {self.gvar.callers_method_name} update_buy_order(): {Bcolors.FAIL}file not found{Bcolors.ENDC} {csv_file=} ")      
    
            return          
    
        ######################################## load buy order file by coin
        def get_buy_order(self) -> pd.DataFrame:  # return df
            symbol = self.coin.symbol
    
            csv_file = self.folder_trading_type + f'buy_order({symbol}).csv'  
            # desktop-pc/bot/buy_sell/buy_order(BTC_JPY).csv  
            # desktop-pc/bot/sell_buy/buy_order(BTC_JPY).csv      
        
            if self.file_exists(csv_file):                
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.BUY_ORDER 
    
                # buy order file: buy_order(BTC_JPY).csv
                # ----------------------------------------------------------------------------------------------------------
                #  #   Column                    Dtype         
                # ----------------------------------------------------------------------------------------------------------        
                #  0   buy_time                  datetime64[utc]    ★ PK (unique) : copy from the GMO dataframe (time UTC)      
                #  1   qty                       float64       
                #  2   price                     float64          
                #  3   real_qty                  float64            sum(sub_order->real_qty)       
                #  4   real_price                float64            mean(sub_order->real_price)        
                #  5   real_fee                  float64            sum(sub_order->real_fee)                                     
                #  6   sell_time                 datetime64[utc]    => link to sell order       
                #  7   log_time                  datetime64[ns]  
                # ----------------------------------------------------------------------------------------------------------
    
                df['buy_time'] = pd.to_datetime(df['buy_time'], utc=True)       # object => UTC time(aware)
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time(aware)        
                df['log_time'] = pd.to_datetime(df['log_time'])                 # object => ns time (jp time)                           
            else:
                df = pd.DataFrame() # empty dataframe                           
            # end of if self.file_exists(csv_file):
    
            return df
    
        ############################################# dump buy order file by coin
        def dump_buy_order_with_header(self) -> None:
            symbol = self.coin.symbol
    
            csv_file = self.folder_trading_type + f'buy_order({symbol})_header.csv'  
            # desktop-pc/bot/buy_sell/buy_order(BTC_JPY)_header.csv  
            # desktop-pc/bot/sell_buy/buy_order(BTC_JPY)_header.csv 
    
            df = self.get_buy_order()
            if df.shape[0] > 0:
                df['jp_time'] = df['buy_time'].apply(lambda x: x + timedelta(hours=9))  # convert utc to local(jp) time
                df.to_csv(csv_file, index=False)  # save a csv file (overwrite)          
    
            return
    
        ################################################################################################################################################################################################################################## append buy sub order log  
        def write_buy_order_sub(self, buy_time: dt.datetime.utcnow, sell_time: dt.datetime.utcnow, buy_order_id: str, sell_order_id: str, position_id: str, qty: float, price: float, real_qty=0.0, real_price=0.0, real_fee=0.0) -> None:
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal
    
            get_price_count = 0; sold = False; stop_loss = False; cancelled = False; log_time = dt.datetime.now()          
            # 'buy_time','buy_order_id','position_id','qty','price','real_qty','real_price','real_fee','get_price_count','sold','stop_loss','cancelled','sell_time','sell_order_id','log_time'
            data = [[buy_time, buy_order_id, position_id, qty, price, real_qty, real_price, real_fee, get_price_count, sold, stop_loss, cancelled, sell_time, sell_order_id, log_time]]   
            df = pd.DataFrame(data, columns=Gmo_dataframe.BUY_ORDER_SUB)  
    
            # append a new record into the buy order sub csv file 
            csv_file = self.folder_trading_type + f'buy_order_sub({symbol}).csv'  
            # desktop-pc/bot/buy_sell/buy_order_sub(BTC_JPY).csv
            # desktop-pc/bot/sell_buy/buy_order_sub(BTC_JPY).csv
            df.to_csv(csv_file, mode='a', header=False, index=False)   # save a csv file (append mode)
            self.debug.trace_write(f".... {self.gvar.callers_method_name} write_buy_order_sub({buy_order_id=}, {position_id=}, {qty=:,.{_q_}f}, {price=:,.{_p_}f}, {real_qty=:,.{_q_}f}, {real_price=:,.{_p_}f}): ▶ {df.shape[0]=} ")              
            
            return
       
        ################################################################################################################################### update buy order sub file (multiple columns)
        def update_buy_order_sub(self, buy_time: dt.datetime.utcnow, buy_order_id: str, col_name_list: list, col_value_list: list) -> None:  # PK(buy_time + buy_order_id)
            symbol = self.coin.symbol
    
            csv_file = self.folder_trading_type + f'buy_order_sub({symbol}).csv'  
            # desktop-pc/bot/buy_sell/buy_order_sub(BTC_JPY).csv     
            # desktop-pc/bot/sell_buy/buy_order_sub(BTC_JPY).csv  
    
            if self.file_exists(csv_file):    
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.BUY_ORDER_SUB
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # object => UTC time(aware)    
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time(aware)                
                df['log_time']  = pd.to_datetime(df['log_time'])                # object => ns time (jp time)    
    
                df['buy_order_id']  = df['buy_order_id'].astype(str)            # int64 => string 
                df['sell_order_id'] = df['sell_order_id'].astype(str)           # int64 => string     
                df['position_id']   = df['position_id'].astype(str)             # int64 => string            
    
                filter_mask = (df['buy_time'] == buy_time) & (df['buy_order_id'] == buy_order_id)   # PK(buy_time + buy_order_id)
                dfx = df[filter_mask]  
    
                # found buy order sub ?
                if dfx.shape[0] > 0:
                    df.loc[filter_mask, col_name_list] = col_value_list         # update 
                    df.to_csv(csv_file, header=False, index=False)              # save a csv file (overwrite mode)  
                    self.debug.trace_write(f".... {self.gvar.callers_method_name} update_buy_order_sub({buy_order_id=}, {col_name_list=}, {col_value_list=}): ▶ {df[filter_mask].shape[0]=} ")                 
                else: # not found buy order sub                   
                    self.debug.print_log(f".... {self.gvar.callers_method_name} update_buy_order_sub({buy_time=:%Y-%m-%d %H:%M:%S}, {buy_order_id=}): {Bcolors.FAIL}buy order sub not found{Bcolors.ENDC} ")                                
                    self.debug.sound_alert(3)                 
            else:
                self.debug.print_log(f".... {self.gvar.callers_method_name} update_buy_order_sub(): {Bcolors.FAIL}file not found{Bcolors.ENDC} {csv_file=} ")            
    
            return             
    
        ############################################ load buy order sub file by coin
        def get_buy_order_sub(self) -> pd.DataFrame:    # return df
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'buy_order_sub({symbol}).csv'  
            # desktop-pc/bot/buy_sell/buy_order_sub(BTC_JPY).csv   
            # desktop-pc/bot/sell_buy/buy_order_sub(BTC_JPY).csv     
        
            if self.file_exists(csv_file):                
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.BUY_ORDER_SUB 
    
                # buy order sub file: buy_order_sub(BTC_JPY).csv
                # -----------------------------------------------------------------------------------------------------------------------
                #  #   Column                    Dtype         
                # -----------------------------------------------------------------------------------------------------------------------         
                #  0   buy_time                  datetime64[utc]    ★ PK1 (non unique) 
                #  1   buy_order_id              object             ★ PK2 (unique)
                #  2   position_id               object             list of position_id : 'positionId1;positionId2;positionId3  
                #  3   qty                       float64       
                #  4   price                     float64          
                #  5   real_qty                  float64            sum(child->real_qty)       
                #  6   real_price                float64            mean(child->real_price)        
                #  7   real_fee                  float64            sum(child->real_fee)     
                #  8   get_price_count           float64            used for get price count or stop loss count
                #  9   sold                      bool 
                # 10   stop_loss                 bool    
                # 11   cancelled                 bool 
                # 12   sell_time                 datetime64[utc]    => link to sell order log 
                # 13   sell_order_id             object             list of sell_order_id : 'orderId1;orderId2;orderId3'                                            
                # 14   log_time                  datetime64[ns]  
                # ----------------------------------------------------------------------------------------------------------------------
    
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # object => UTC time(aware)    
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time(aware)                
                df['log_time']  = pd.to_datetime(df['log_time'])                # object => ns time (jp time)    
    
                df['buy_order_id']  = df['buy_order_id'].astype(str)            # int64 => string 
                df['sell_order_id'] = df['sell_order_id'].astype(str)           # int64 => string     
                df['position_id']   = df['position_id'].astype(str)             # int64 => string                  
            else:
                df = pd.DataFrame()                             
            # end of if self.file_exists(csv_file):
    
            return df
    
        ################################################# dump buy order sub file by coin
        def dump_buy_order_sub_with_header(self) -> None:
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'buy_order_sub({symbol})_header.csv'  
            # desktop-pc/bot/buy_sell/buy_order_sub(BTC_JPY)_header.csv  
            # desktop-pc/bot/sell_buy/buy_order_sub(BTC_JPY)_header.csv  
    
            df = self.get_buy_order_sub()
            if df.shape[0] > 0:
                df['jp_time'] = df['buy_time'].apply(lambda x: x + timedelta(hours=9))  # convert utc to local(jp) time
                df.to_csv(csv_file, index=False)  # overwrite  
    
            return    
    
        ############################################################################################################################################################################################################################### append buy order child file
        def write_buy_order_child(self, buy_time: dt.datetime.utcnow, buy_order_id: str, sell_time: dt.datetime.utcnow, sell_order_id: str, position_id: str , qty=0.0, price=0.0, real_qty=0.0, real_price=0.0, real_fee=0.0) -> None: 
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal
    
            log_time = dt.datetime.now()
            # 'buy_time','buy_order_id','position_id','qty','price','real_qty','real_price','real_fee','sell_time','sell_order_id','log_time'
            data = [[buy_time, buy_order_id, position_id, qty, price, real_qty, real_price, real_fee, sell_time, sell_order_id, log_time]]   
            df = pd.DataFrame(data, columns=Gmo_dataframe.BUY_ORDER_CHILD)  
    
            # append a new record into the buy order child csv file 
            csv_file = self.folder_trading_type + f'buy_order_child({symbol}).csv'  
            # desktop-pc/bot/buy_sell/buy_order_child(BTC_JPY).csv
            # desktop-pc/bot/sell_buy/buy_order_child(BTC_JPY).csv
    
            df.to_csv(csv_file, mode='a', header=False, index=False)   # save a csv file (append mode)
            self.debug.trace_write(f".... {self.gvar.callers_method_name} write_buy_order_child({buy_order_id=}, {position_id=}, {real_qty=:,.{_q_}f}, {real_price=:,.{_p_}f}): ▶ {df.shape[0]=} ") 
    
            return
    
        ############################################### get buy order child by coin 
        def get_buy_order_child(self) -> pd.DataFrame : # return df : PK(buy_time + buy_order_id + position_id)
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'buy_order_child({symbol}).csv'  
            # desktop-pc/bot/buy_sell/buy_order_child(BTC_JPY).csv  
            # desktop-pc/bot/sell_buy/buy_order_child(BTC_JPY).csv       
    
            if self.file_exists(csv_file):          
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.BUY_ORDER_CHILD 
    
                # buy order log file: buy_order_child_log(BTC_JPY).csv
                # ----------------------------------------------------------------------------------------------------------
                #  #   Column                    Dtype         
                # ----------------------------------------------------------------------------------------------------------         
                #  0   buy_time                  datetime64[utc]    ★ PK1 (non unique)
                #  1   buy_order_id              object             ★ PK2 (non unique)   
                #  2   position_id               object             ★ PK3 (unique) 
                #  3   qty                       float64       
                #  4   price                     float64                          
                #  5   real_qty                  float64           
                #  6   real_price                float64         
                #  7   real_fee                  float64      
                #  8   sell_time                 datetime64[utc]    => link to sell order   
                #  9   sell_order_id             object             list of sell_order_id : 'orderId1;orderId2;orderId3'                                                     
                # 10   log_time                  datetime64[ns]  
                # ----------------------------------------------------------------------------------------------------------
    
                df['buy_time'] = pd.to_datetime(df['buy_time'], utc=True)       # object => UTC time (aware)  
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time (aware) 
                df['log_time']  = pd.to_datetime(df['log_time'])                # object => ns time (jp time)
    
                df['buy_order_id']  = df['buy_order_id'].astype(str)            # int64 => string  
                df['sell_order_id'] = df['sell_order_id'].astype(str)           # int64 => string
                df['position_id'] = df['position_id'].astype(str)               # int64 => string                                   
            else:
                df = pd.DataFrame()        
            # end of if self.file_exists(csv_file):
    
            return df
    
        ################################################### dump buy order child file by coin
        def dump_buy_order_child_with_header(self) -> None:
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'buy_order_child({symbol})_header.csv'  
            # desktop-pc/bot/buy_sell/buy_order_child(BTC_JPY)_header.csv  
            # desktop-pc/bot/sell_buy/buy_order_child(BTC_JPY)_header.csv 
            df = self.get_buy_order_child()
            if df.shape[0] > 0:
                df['jp_time'] = df['buy_time'].apply(lambda x: x + timedelta(hours=9))  # convert utc to local(jp) time
                df.to_csv(csv_file, index=False)  # save a csv file (overwrite)          
            return
    
        ###################################################################################################################################################################### append sell order file
        def write_sell_order(self, sell_time: dt.datetime.utcnow, buy_time: dt.datetime.utcnow, qty: float, price: float, real_qty=0.0, real_price=0.0, real_fee=0.0) -> None:      
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal        
    
            log_time = dt.datetime.now()
            # 'sell_time','qty','price','real_qty','real_price','real_fee','buy_time','log_time'
            data = [[sell_time, qty, price, real_qty, real_price, real_fee, buy_time, log_time]]   
            df = pd.DataFrame(data, columns=Gmo_dataframe.SELL_ORDER)        
            
            # append a new record into the sell order file 
            csv_file = self.folder_trading_type + f'sell_order({symbol}).csv' 
            # desktop-pc/bot/buy_sell/sell_order(BTC_JPY).csv 
            # desktop-pc/bot/sell_buy/sell_order(BTC_JPY).csv 
    
            df.to_csv(csv_file, mode='a', header=False, index=False)   # save a csv file (append mode)        
            self.debug.trace_write(f".... {self.gvar.callers_method_name} write_sell_order({sell_time=:%Y-%m-%d %H:%M:%S}, {qty=:,.{_q_}f}, {price=:,.{_p_}f}): ▶ {df.shape[0]=} ")     
             
            return
    
        ################################################################################################################ update sell order file (multiple columns)
        def update_sell_order(self, sell_time: dt.datetime.utcnow, col_name_list: list, col_value_list: list) -> object:  # PK(sell_time)
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'sell_order({symbol}).csv'  
            # desktop-pc/bot/buy_sell/sell_order(BTC_JPY).csv   
            # desktop-pc/bot/sell_buy/sell_order(BTC_JPY).csv       
    
            if self.file_exists(csv_file):    
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.SELL_ORDER
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # utc time (aware)
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # utc time (aware)   
                df['log_time']  = pd.to_datetime(df['log_time'])                # jp time
    
                filter_mask = df['sell_time'] == sell_time                      # PK(sell_time)
                dfx = df[filter_mask]
    
                # found sell order ?
                if dfx.shape[0] > 0:
                    df.loc[filter_mask, col_name_list] = col_value_list         # update 
                    df.to_csv(csv_file, header=False, index=False)              # save a csv file (overwrite mode)  
                    self.debug.trace_write(f".... {self.gvar.callers_method_name} update_sell_order({sell_time=:%Y-%m-%d %H:%M:%S}, {col_name_list=}, {col_value_list=}): ▶ {df[filter_mask].shape[0]=} ")                          
                else: # not found sell order
                    self.debug.print_log(f".... {self.gvar.callers_method_name} update_sell_order({sell_time=:%Y-%m-%d %H:%M:%S}): {Bcolors.FAIL}sell order not found{Bcolors.ENDC}  ") 
                    self.debug.sound_alert(3) 
            else:
                self.debug.print_log(f".... {self.gvar.callers_method_name} update_sell_order(): {Bcolors.FAIL}file not found{Bcolors.ENDC} {csv_file=} ") 
    
            return    
    
        ######################################### load sell order log by coin
        def get_sell_order(self) -> pd.DataFrame:   # return df
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'sell_order({symbol}).csv'  
            # desktop-pc/bot/buy_sell/sell_order(BTC_JPY).csv      
            # desktop-pc/bot/sell_buy/sell_order(BTC_JPY).csv 
    
            if self.file_exists(csv_file):          
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.SELL_ORDER
    
                # sell order log file: sell_order(BTC_JPY).csv 
                # ------------------------------------------------------------------------------------------------------------
                #  #   Column                    Dtype         
                # ------------------------------------------------------------------------------------------------------------         
                #  0   sell_time                 datetime64[utc]    ★ PK1 (unique) : copy from the GMO dataframe (time UTC)      
                #  1   qty                       float64       
                #  2   price                     float64    
                #  3   real_qty                  float64            sum(sub_order->real_qty)    
                #  4   real_price                float64            mean(sub_order->real_price)      
                #  5   real_fee                  float64            sum(sub_order->real_fee)      
                #  6   buy_time                  datetime64[utc]    => link to buy order log          
                #  7   log_time                  datetime64[ns]  
                # ------------------------------------------------------------------------------------------------------------ 
     
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time (aware)
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # object => UTC time (aware)       
                df['log_time']  = pd.to_datetime(df['log_time'])                # object => ns time (jp time)                                     
            else:
                df = pd.DataFrame()                               
            # end of if self.file_exists(csv_file):
    
            return df        
    
        ############################################## dump sell order file by coin
        def dump_sell_order_with_header(self) -> None:
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'sell_order({symbol})_header.csv'  
            # desktop-pc/bot/buy_sell/sell_order(BTC_JPY)_header.csv  
            # desktop-pc/bot/sell_buy/sell_order(BTC_JPY)_header.csv  
    
            df = self.get_sell_order()
            if df.shape[0] > 0:
                df['jp_time'] = df['sell_time'].apply(lambda x: x + timedelta(hours=9))  # convert utc to local(jp) time
                df.to_csv(csv_file, index=False)  # save a csv file (overwrite)
    
            return              
    
        ################################################################################################################################################################################################################################### append sell order sub
        def write_sell_order_sub(self, sell_time: dt.datetime.utcnow, buy_time: dt.datetime.utcnow, sell_order_id: str, buy_order_id: str, position_id: str, qty: float, price: float, real_qty=0.0, real_price=0.0, real_fee=0.0) -> None:   
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal            
    
            get_price_count=0; bought=False; stop_loss=False; cancelled=False; log_time=dt.datetime.now()      
            # 'sell_time','sell_order_id','position_id','qty','price','real_qty','real_price','real_fee','get_price_count','bought','stop_loss','cancelled','buy_time','buy_order_id','log_time'
            data = [[sell_time, sell_order_id, position_id, qty, price, real_qty, real_price, real_fee, get_price_count, bought, stop_loss, cancelled, buy_time, buy_order_id, log_time]]   
            df = pd.DataFrame(data, columns=Gmo_dataframe.SELL_ORDER_SUB)        
            
            # append a new record into the sell order sub file 
            csv_file = self.folder_trading_type + f'sell_order_sub({symbol}).csv' 
            # desktop-pc/bot/buy_sell/sell_order_sub(BTC_JPY).csv
            # desktop-pc/bot/sell_buy/sell_order_sub(BTC_JPY).csv
    
            df.to_csv(csv_file, mode='a', header=False, index=False)   # save a csv file (append mode)                          
            self.debug.trace_write(f".... {self.gvar.callers_method_name} write_sell_order_sub({sell_order_id=}, {position_id=}, {qty=:,.{_q_}f}, {price=:,.{_p_}f}, {real_qty=:,.{_q_}f}, {real_price=:,.{_p_}f}): ▶ {df.shape[0]=} ")   
            
            return      
       
        ###################################################################################################################################### update sell order sub file (multiple columns)
        def update_sell_order_sub(self, sell_time: dt.datetime.utcnow, sell_order_id: str, col_name_list: list, col_value_list: list) -> None: # PK(sell_time + sell_order_id)
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'sell_order_sub({symbol}).csv'  
            # desktop-pc//bot/buy_sell/sell_order_sub(BTC_JPY).csv     
    
            if self.file_exists(csv_file):    
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.SELL_ORDER_SUB
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time (aware)      
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # object => UTC time (aware)             
                df['log_time']  = pd.to_datetime(df['log_time'])                # object => ns time (jp time)
                
                df['sell_order_id'] = df['sell_order_id'].astype(str)           # int64 => string 
                df['buy_order_id']  = df['buy_order_id'].astype(str)            # int64 => string   
                df['position_id']   = df['position_id'].astype(str)             # int64 => string             
    
                filter_mask = (df['sell_time'] == sell_time) & (df['sell_order_id'] == sell_order_id) # PK(sell_time + sell_order_id)
                dfx = df[filter_mask]
                
                # found sell sub order ?
                if dfx.shape[0] > 0:
                    df.loc[filter_mask, col_name_list] = col_value_list         # update multiple columns
                    df.to_csv(csv_file, header=False, index=False)              # overwrite mode  
                    self.debug.trace_write(f".... {self.gvar.callers_method_name} update_sell_order_sub({sell_time=:%Y-%m-%d %H:%M:%S}, {sell_order_id=}, {col_name_list=}, {col_value_list=}): ▶ {df[filter_mask].shape[0]=} ")                      
                else: # not found sell order sub   
                    self.debug.print_log(f".... {self.gvar.callers_method_name} update_sell_order_sub({sell_time=:%Y-%m-%d %H:%M:%S}, {sell_order_id=}): {Bcolors.FAIL}sell order sub not found{Bcolors.ENDC} ") 
                    self.debug.sound_alert(3) 
            else:
                self.debug.print_log(f".... {self.gvar.callers_method_name} update_sell_order_sub(): {Bcolors.FAIL}file not found{Bcolors.ENDC} '{csv_file}' ")        
        
        ############################################# load sell order sub by coin
        def get_sell_order_sub(self) -> pd.DataFrame:   # return df
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'sell_order_sub({symbol}).csv'  
            # desktop-pc/bot//buy_sell/sell_order_sub(BTC_JPY).csv      
            # desktop-pc/bot//sell_buy/sell_order_sub(BTC_JPY).csv   
    
            if self.file_exists(csv_file):          
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.SELL_ORDER_SUB
    
                # sell sub_order log file: sell_order_sub(BTC_JPY).csv 
                # ---------------------------------------------------------------------------------------------------------------
                #  #   Column                    Dtype         
                # ---------------------------------------------------------------------------------------------------------------         
                #  0   sell_time                 datetime64[utc]    ★ PK1 (non unique)    
                #  1   sell_order_id             object             ★ PK2 (unique)
                #  2   position_id               object             list of position_id : 'posiitonId1;positionId2;positionId3'   
                #  3   qty                       float64       
                #  4   price                     float64    
                #  5   real_qty                  float64            sum(child->real_qty)    
                #  6   real_price                float64            mean(child->real_price)      
                #  7   real_fee                  float64            sum(child->real_fee)      
                #  8   get_price_count           float64            used for get price count or stop loss count        
                #  9   bought                    bool 
                # 10   stop_loss                 bool                   
                # 11   cancelled                 bool     
                # 12   buy_time                  datetime64[utc]    => link to buy order 
                # 13   buy_order_id              object             => link to buy order sub (non unique)        
                # 14   log_time                  datetime64[ns]  
                # ----------------------------------------------------------------------------------------------------------------
     
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time (aware)      
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # object => UTC time (aware)             
                df['log_time']  = pd.to_datetime(df['log_time'])                # object => ns time (jp time)
                
                df['sell_order_id'] = df['sell_order_id'].astype(str)           # int64 => string 
                df['buy_order_id']  = df['buy_order_id'].astype(str)            # int64 => string   
                df['position_id']   = df['position_id'].astype(str)             # int64 => string                                  
            else:
                df = pd.DataFrame()                             
            # end of if self.file_exists(csv_file):
    
            return df   
    
        ################################################## dump sell order sub file by coin
        def dump_sell_order_sub_with_header(self) -> None:
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'sell_order_sub({symbol})_header.csv'  
            # desktop-pc/bot/buy_sell/sell_order_sub(BTC_JPY)_header.csv  
            # desktop-pc/bot/sell_buy/sell_order_sub(BTC_JPY)_header.csv  
    
            df = self.get_sell_order_sub()
            if df.shape[0] > 0:
                df['jp_time'] = df['sell_time'].apply(lambda x: x + timedelta(hours=9))  # convert utc to local(jp) time
                df.to_csv(csv_file, index=False)  # save a csv file (overwrite)
    
            return               
    
        ########################################################################################################################################################################################### append sell order child log into the sell order child log file
        def write_sell_order_child(self, sell_time: dt.datetime.utcnow, sell_order_id: str, buy_time: dt.datetime.utcnow, buy_order_id: str, position_id: str, qty=0.0, price=0.0, real_qty=0.0, real_price=0.0, real_fee=0.0) -> None: 
            symbol = self.coin.symbol; _q_ = self.coin.qty_decimal; _p_ = self.coin.price_decimal
    
            log_time=dt.datetime.now()
            # 'sell_time','sell_order_id','position_id','qty','price','real_qty','real_price','real_fee','buy_time','buy_order_id','log_time'
            data = [[sell_time, sell_order_id, position_id, qty, price, real_qty, real_price, real_fee, buy_time, buy_order_id, log_time]]   
            df = pd.DataFrame(data, columns=Gmo_dataframe.SELL_ORDER_CHILD)  
    
            # append a new record into the sell order child file 
            csv_file = self.folder_trading_type + f'sell_order_child({symbol}).csv'  
            # desktop-pc/bot/buy_sell/sell_order_child(BTC_JPY).csv
            # desktop-pc/bot/sell_buy/sell_order_child(BTC_JPY).csv
    
            df.to_csv(csv_file, mode='a', header=False, index=False)   # save a csv file (append mode)
            self.debug.trace_write(f".... {self.gvar.callers_method_name} write_sell_order_child({sell_order_id=}, {position_id=}, {real_qty=:,.{_q_}f}, {real_price=:,.{_p_}f}): ▶ {df.shape[0]=} ") 
            
            return
    
        ############################################### get sell order child by coin 
        def get_sell_order_child(self) -> pd.DataFrame: # return df : PK(sell_time + sell_order_id + position_id)
            symbol = self.coin.symbol;
            csv_file = self.folder_trading_type + f'sell_order_child({symbol}).csv'  
            # desktop-pc/bot/buy_sell/sell_order_child(BTC_JPY).csv   
            # desktop-pc/bot/sell_buy/sell_order_child(BTC_JPY).csv 
    
            if self.file_exists(csv_file):          
                df = pd.read_csv(csv_file, header=None)             
                df.columns = Gmo_dataframe.SELL_ORDER_CHILD
    
                # sell order child file: sell_order_child(BTC_JPY).csv 
                # --------------------------------------------------------------------------------------------
                #  #   Column                    Dtype         
                # --------------------------------------------------------------------------------------------         
                #  0   sell_time                 datetime64[utc]    ★ PK1 (non unique)
                #  1   sell_order_id             object             ★ PK2 (non unique)     
                #  2   position_id               object             ★ PK3 (non unique)                          
                #  3   qty                       float64       
                #  4   price                     float64  
                #  5   real_qty                  float64             
                #  6   real_price                float64        
                #  7   real_fee                  float64    
                #  8   buy_time                  datetime64[utc]    => link to buy order 
                #  9   buy_order_id              object             => link to buy order sub (non unique)                                                     
                # 10   log_time                  datetime64[ns]  
                # ---------------------------------------------------------------------------------------------
    
                df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)     # object => UTC time (aware)  
                df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)      # object => UTC time (aware) 
                df['log_time']  = pd.to_datetime(df['log_time'])                # object => ns time (jp time)
    
                df['sell_order_id'] = df['sell_order_id'].astype(str)           # int64 => string  
                df['buy_order_id']  = df['buy_order_id'].astype(str)            # int64 => string              
                df['position_id']   = df['position_id'].astype(str)             # int64 => string                                   
            else:
                df = pd.DataFrame()        
            # end of if self.file_exists(csv_file):
    
            return df
    
        #################################################### dump sell order child file by coin
        def dump_sell_order_child_with_header(self) -> None:
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'sell_order_child({symbol})_header.csv'  
            # desktop-pc/bot/buy_sell/sell_order_child(BTC_JPY)_header.csv  
            # desktop-pc/bot/sell_buy/sell_order_child(BTC_JPY)_header.csv  
    
            df = self.get_sell_order_child()
            if df.shape[0] > 0:
                df['jp_time'] = df['sell_time'].apply(lambda x: x + timedelta(hours=9))  # convert utc to local(jp) time
                df.to_csv(csv_file, index=False)  # save a csv file (overwrite)
    
            return                  
    
        ######################################## load order csv file => return (df)
        def get_order_csv(self) -> pd.DataFrame:  # return df  
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'order({symbol}).csv'  
            # desktop-pc/bot/buy_sell/order(BTC_JPY).csv 
            # desktop-pc/bot/sell_sell/order(BTC_JPY).csv                  
     
            # order(BTC).csv file exists ? 
            if self.file_exists(csv_file):                     
                # Load the order(BTC_JPY).csv file
                df = pd.read_csv(csv_file, header=None) 
                if df.shape[0] > 0:
                    df.columns = Gmo_dataframe.ORDER_CSV
    
                    # order file: order(BTC_JPY).csv
                    # ----------------------------------------------------------------------------------------------------------------------
                    #  #   Column                                Dtype
                    # ----------------------------------------------------------------------------------------------------------------------
                    #  1   buy_time                              datetime64[utc]    ★ PK1
                    #  2   sell_time                             datetime64[utc]      
                    #  3   buy_order_id                          object             ★ PK2
                    #  4   sell_order_id                         object             list of sell_order_id : 'orderId1;orderId2;orderId3'      
                    #  5   buy_real_qty                          float64    
                    #  6   sell_real_qty                         float64                
                    #  7   buy_real_price                        float64
                    #  8   sell_real_price                       float64
                    #  9   buy_real_fee                          float64
                    # 10   sell_real_fee                         float64              
                    # 11   real_profit                           float64
                    # 12   accumulated_leverage_fee              float64            
                    # 13   close_count                           int                leverage fee close count         
                    # 14   close_update_date                     datetime64[ns]     leverage fee close date   
                    # 15   order_closed                          bool                                 
                    # 16   stop_loss                             bool
                    # 17   cancelled                             bool
                    # 18   order_open_date                       datetime64[ns]     
                    # 19   order_close_date                      datetime64[ns]      
                    # 20   log_time                              datetime64[ns]     => update every time
                    # -----------------------------------------------------------------------------------------------------------------------
                 
                    df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)          # object => utc time (aware)
                    df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)         # object => utc time (aware)  
                    df['close_update_date']  = pd.to_datetime(df['close_update_date'])  # object => ns time (jp time)  
                    df['order_open_date']    = pd.to_datetime(df['order_open_date'])    # object => ns time (jp time) 
                    df['order_close_date']   = pd.to_datetime(df['order_close_date'])   # object => ns time (jp time)                     
                    df['log_time']  = pd.to_datetime(df['log_time'])                    # object => ns time (jp time)    
    
                    df['buy_order_id'] = df['buy_order_id'].astype(str)                 # int64 => string
                    df['sell_order_id'] = df['sell_order_id'].astype(str)               # int64 => string                         
            else:   # load order dummy data
                df = pd.DataFrame()              
            # end of if self.file_exists(csv_file): 
    
            return df
    
        ################################################################################################################################### update order csv by buy_time + buy_order_id (multiple columns)
        def update_order_csv_buy(self, buy_time: dt.datetime.utcnow, buy_order_id: str, col_name_list: list, col_value_list: list) -> None: # PK(buy_time + buy_order_id)
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'order({symbol}).csv'  
            # desktop-pc/bot/buy_sell/order(BTC_JPY).csv   
            # desktop-pc/bot/sell_buy/order(BTC_JPY).csv       
    
            if self.file_exists(csv_file):      
                df = pd.read_csv(csv_file, header=None)             
                if df.shape[0] > 0:
                    df.columns = Gmo_dataframe.ORDER_CSV 
    
                    df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)          # object => utc time (aware)
                    df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)         # object => utc time (aware)   
                    df['close_update_date']  = pd.to_datetime(df['close_update_date'])  # object => ns time (jp time)     
                    df['order_open_date']    = pd.to_datetime(df['order_open_date'])    # object => ns time (jp time) 
                    df['order_close_date']   = pd.to_datetime(df['order_close_date'])   # object => ns time (jp time)                      
                    df['log_time']  = pd.to_datetime(df['log_time'])                    # object => ns time (jp time)    
    
                    df['buy_order_id'] = df['buy_order_id'].astype(str)                 # int64 => string
                    df['sell_order_id'] = df['sell_order_id'].astype(str)               # int64 => string
    
                    filter_mask = (df['buy_time'] == buy_time) & (df['buy_order_id'] == buy_order_id)   # PK(buy_time + buy_order_id)
    
                    df.loc[filter_mask, col_name_list] = col_value_list                 # update multiple columns
                    df.loc[filter_mask, 'log_time'] = dt.datetime.now()                 # update log_time
                    df.to_csv(csv_file, header=False, index=False)                      # overwrite mode
                    self.debug.trace_write(f".... {self.gvar.callers_method_name} update_order_csv_buy({buy_time=:%Y-%m-%d %H:%M:%S}, {buy_order_id=}, {col_name_list=}, {col_value_list=}): ▶ {df[filter_mask].shape[0]=} ")                  
                else:   # empty dataframe
                    self.debug.print_log(f".... {self.gvar.callers_method_name} update_order_csv_buy({buy_time=:%Y-%m-%d %H:%M:%S}, {buy_order_id=}): {Bcolors.FAIL}dataframe is empty{Bcolors.ENDC} {df[filter_mask].shape[0]=} ") 
            else:
                self.debug.print_log(f".... {self.gvar.callers_method_name} update_order_csv_buy(): {Bcolors.FAIL}file not found{Bcolors.ENDC} {csv_file=} ")     
    
            return    
    
        ###################################################################################################################################### update order csv by sell_time + sell_order_id (multiple columns)
        def update_order_csv_sell(self, sell_time: dt.datetime.utcnow, sell_order_id: str, col_name_list: list, col_value_list: list) -> None: # PK(sell_time + sell_order_id)
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'order({symbol}).csv'  
            # desktop-pc/bot/buy_sell/order(BTC_JPY).csv       
            # desktop-pc/bot/sell_buy/order(BTC_JPY).csv    
    
            if self.file_exists(csv_file):      
                df = pd.read_csv(csv_file, header=None)             
                if df.shape[0] > 0:
                    df.columns = Gmo_dataframe.ORDER_CSV 
    
                    df['buy_time']  = pd.to_datetime(df['buy_time'], utc=True)          # object => utc time (aware)
                    df['sell_time'] = pd.to_datetime(df['sell_time'], utc=True)         # object => utc time (aware)      
                    df['close_update_date']  = pd.to_datetime(df['close_update_date'])  # object => ns time (jp time)   
                    df['order_open_date']    = pd.to_datetime(df['order_open_date'])    # object => ns time (jp time) 
                    df['order_close_date']   = pd.to_datetime(df['order_close_date'])   # object => ns time (jp time)                     
                    df['log_time']  = pd.to_datetime(df['log_time'])                    # object => ns time (jp time)    
    
                    df['buy_order_id'] = df['buy_order_id'].astype(str)                 # int64 => string
                    df['sell_order_id'] = df['sell_order_id'].astype(str)               # int64 => string
    
                    filter_mask = (df['sell_time'] == sell_time) & (df['sell_order_id'] == sell_order_id)   # PK(sell_time + sell_order_id)
                    df.loc[filter_mask, col_name_list] = col_value_list                 # update multiple columns
                    df.loc[filter_mask, 'log_time'] = dt.datetime.now()                 # update log_time
                    df.to_csv(csv_file, header=False, index=False)                      # overwrite mode
                    self.debug.trace_write(f".... {self.gvar.callers_method_name} update_order_csv_sell({sell_time=:%Y-%m-%d %H:%M:%S}, {sell_order_id=}, {col_name_list=}, {col_value_list=}): ▶ {df[filter_mask].shape[0]=} ")                   
                else:
                    self.debug.print_log(f".... {self.gvar.callers_method_name} update_order_csv_sell({sell_time=:%Y-%m-%d %H:%M:%S}, {sell_order_id=}): {Bcolors.FAIL}dataframe is empty{Bcolors.ENDC} {df[filter_mask].shape[0]=} ") 
            else:
                self.debug.print_log(f".... {self.gvar.callers_method_name} update_order_csv_sell(): {Bcolors.FAIL}file not found{Bcolors.ENDC} {csv_file=} ")     
    
            return     
    
        ######################################### load gmo master csv file => return (df)
        def get_gmo_master(self) -> pd.DataFrame:  
            symbol = self.coin.symbol
            csv_file = self.folder_trading_type + f'master({symbol}).csv'          
            # desktop-pc/bot/buy_sell/master(BTC_JPY).csv       
            # desktop-pc/bot/sell_sell/master(BTC_JPY).csv           
      
            # master(BTC).csv file exists ? 
            if self.file_exists(csv_file):                     
                # Load the master(BTC_JPY).csv file
                df = pd.read_csv(csv_file) 
                if df.shape[0] > 0:    
                    # gmo master file: master(BTC_JPY).csv
                    # ----------------------------------------------------------------------------------
                    #  #   Column                    Dtype              
                    # ---------------------------------------------------------------------------------
                    #  0   price                    float64   buy/sell price           
                    #  1   side                     object    'BUY' or 'SELL'             
                    #  2   size                     float64            
                    #  3   timestamp                datetime64[ns, UTC] ★ UTC descending order      
                    # --------------------------------------------------------------------------------                       
                    df['timestamp'] = pd.to_datetime(df['timestamp'], utc=True, errors='coerce')   # UTC (ware) ★ errors='coerce' => NaT or errors='ignore'            
                           
            else:   # load gmo master dummy data
                df = pd.DataFrame()              
            # end of if self.file_exists(csv_file): 
    
            return df