Python {Article113}

ようこそ「Python」へ...

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

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

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

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

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

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

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

BOTのDebugクラスを作成する

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

    ここではDebugクラスを作成して__init__()と__str__()メソッドを追加します。 行8ではWindows用のサウンドライブラリを取り込んでいます。 行13ではBcolorsクラス、Gvarクラスを取り込んでいます。

    行27-29では__init__()メソッドを定義しています。 __init__()メソッドは、Debugクラスのインスタンスを生成したときに自動的に呼ばれます。 Debugクラスのインスタンスを生成するときは、引数にGvarのオブジェクトを指定します。

    行28ではgvarプロパティ(Pythonでは属性と呼ぶ)にGvarのオブジェクトを設定しています。 行29ではfolder_gmoプロパティにBOTのフォルダ名を設定します。 フォルダ名はGvarクラスのdomainとexchangeプロパティから取得して生成します。

    行31-32では__str__()メソッドを定義しています。 このメソッドではDebugクラスからgvarとfolder_gmoのプロパティを取得して返します。 __str__()メソッドはDebugクラスをprint()等で参照したときに自動的に呼ばれます。 __str__()メソッドの詳しいことは、 「記事(Article087)」で解説しています。

    debug.py:
    # debug.py
    
    """
    Debug class    
    """
    
    ### import the libraries
    import winsound
    
    from time import sleep  
    import datetime as dt
    
    from lib.base import Bcolors, Gvar
    
    import warnings
    warnings.simplefilter('ignore')
    
    ############ Debug class
    class Debug:
        """       
        __init__(self, gvar)
        print_log()
        trace_write(), trace_warn(), trace_error()
        sound_alert()
        """
               
        def __init__(self, gvar: object) -> None:
            self.gvar = gvar                        
            self.folder_gmo = f'{self.gvar.domain}/{self.gvar.exchange}/'  # desktop-pc/bot/
    
        def __str__(self) -> str:
            return f"Debug({self.gvar=}, {self.folder_gmo=})"

    click image to zoom!
    図1
    図1ではDebugクラスのプロパティを表示しています。


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

    ここではDebugクラスにprint_log()メソッドを追加しています。 このメソッドはGvarクラスのdebug_modeプロパティが「True/False」いずれのときでも画面とログファイルにを出力します。

    行6-8ではログファイルのファイル名を生成しています。 ファイル名は「log(yyyymmdd).txt」になります。 「yyyymmdd」は当日のシステム日付になります。

    行11-20ではテキスト文字からエスケープシーケンス(ESC)を除去しています。

    行23-31ではテキスト文字をログファイルに出力しています。 行34-37ではテキスト文字を画面に表示しています。 テキスト文字には当日の「日時」が追加されます。

    debug.py:
        ###############################################     
        def print_log(self, msg: str, msg2=any) ->None:   
            msg = str(msg)  # cast string
    
            # write log to a txt file
            now = dt.datetime.now() # current date and time
            date_str = now.strftime('%Y%m%d')   # 20220924
            txt_file = self.folder_gmo + f'log({date_str}).txt' # desktop-pc/bot/log(20220924).txt
        
            # remove ESC 
            log_msg = msg.replace(Bcolors.HEADER,'').replace(Bcolors.OKBLUE,'').replace(Bcolors.OKCYAN,'')
            log_msg = log_msg.replace(Bcolors.OKGREEN,'').replace(Bcolors.WARNING,'').replace(Bcolors.FAIL,'')
            log_msg = log_msg.replace(Bcolors.ENDC,'').replace(Bcolors.BOLD,'').replace(Bcolors.UNDERLINE,'')
    
            # remoce ESC
            if msg2 != any:
                msg2 = str(msg2)    # cast msg2
                log_msg2 = msg2.replace(Bcolors.HEADER,'').replace(Bcolors.OKBLUE,'').replace(Bcolors.OKCYAN,'')
                log_msg2 = log_msg2.replace(Bcolors.OKGREEN,'').replace(Bcolors.WARNING,'').replace(Bcolors.FAIL,'')
                log_msg2 = log_msg2.replace(Bcolors.ENDC,'').replace(Bcolors.BOLD,'').replace(Bcolors.UNDERLINE,'')        
        
            # append a msg, msg2 into the log file => log(YYYYMMDD).txt
            f = open(txt_file, 'a', encoding='utf-8') 
    
            f.write(log_msg)
            if msg2 != any:
                f.write(', ' + log_msg2)
            f.write(f" [{now.strftime('%Y-%m-%d %H:%M:%S')}]")
            f.write('\n')
         
            f.close()
    
            # print a msg, msg2 to the screen
            if msg2 == any:
                print(msg, f"[{Bcolors.OKCYAN}{now.strftime('%Y-%m-%d %H:%M:%S')}{Bcolors.ENDC}]")
            else:
                print(msg, msg2, f"[{Bcolors.OKCYAN}{now.strftime('%Y-%m-%d %H:%M:%S')}{Bcolors.ENDC}]")

    click image to zoom!
    図2-1
    図2-1はデモプログラムの実行結果です。 Gvarクラスのdebug_modeプロパティが「True/False」いずれの場合も画面に表示されています。


    click image to zoom!
    図2-2
    図2-2はログファイルの内容です。


  3. Debugクラスにtrace_write(), trace_warn(), trace_error()メソッドを追加する

    ここではDebugクラスにtrace系の3種類のメソッドを追加しています。 trace系のメソッドはGvarクラスのdebug_modeプロパティが「True」の場合のみ画面とログファイルに出力します。 trace_write()は白色、trace_warn()は黄色、trace_error()は赤色で表示します。

    BOTで仮想トレードするときは、 Gvarクラスを「debug_mode=True」にしてDebugクラスのtrace系のメソッドでパラメータを調整するためのさまざまな情報を表示させます。 そして、リアルトレードするときは「debug_mode=False」にして必要最小限の情報のみ表示させます。

    debug.py:
        ########################################  
        def trace_write(self, msg: str) -> None:
            if self.gvar.debug_mode:  self.print_log(msg)
    
        #######################################  
        def trace_warn(self, msg: str) -> None:
            if self.gvar.debug_mode:  self.print_log(f'{Bcolors.WARNING}{msg}{Bcolors.ENDC}')  
    
        ######################################## 
        def trace_error(self, msg: str) -> None:
            if self.gvar.debug_mode:  self.print_log(f'{Bcolors.FAIL}{msg}{Bcolors.ENDC}')

    click image to zoom!
    図3-1
    図3-1は実行結果です。 trace系のメソッドは、Gvarクラスのdebug_modeプロパティが「True」のときのみ表示されています。


    click image to zoom!
    図3-2
    図3-2はログファイルの内容です。


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

    ここではDebugクラスにsound_alert()メソッドを追加します。 このメソッドは引数で指定した回数分警告音を鳴らします。

    行4の周波数(単位:ヘルツ)を変更すると音を変えることができます。 各自のお好みの音にカスタマイズしてください。 行5-7のforループでは、指定した回数だけ警告音を0.5秒間隔で鳴らします。

    sound_alert()は、仮想通貨の注文が約定したり、BOTで深刻なエラー等が発生したときに使うと便利です。

    debug.py:
        ####################################### 
        def sound_alert(self, count=1) -> None:
            duration = 1000   # milliseconds
            freq = 440  # Hz
            for i in range(count):
                winsound.Beep(freq, duration) 
                sleep(0.5)

    click image to zoom!
    図4-1
    図4-1は実行結果です。 ここでは警告音を1回鳴らして3秒スリープし、 次に警告音を3回鳴らして3秒スリープし、 最後に警告音を5回鳴らしています。


    click image to zoom!
    図4-2
    図4-2はWindows 11のレコーダで録音した画像です。 Audioの再生ボタンをクリックすると実際の警告音を聴くことができます。


  5. Debugクラスのすべてを掲載

    
    # debug.py
    
    """
    Debug class    
    """
    
    ### import the libraries
    import winsound
    
    from time import sleep  
    import datetime as dt
    
    from lib.base import Bcolors, Gvar
    
    import warnings
    warnings.simplefilter('ignore')
    
    ############ Debug class
    class Debug:
        """       
        __init__(self), __init__(self, gvar)
        print_log()
        trace_write(), trace_warn(), trace_error()
        sound_alert()
        """
               
        #########################################
        def __init__(self, gvar: object) -> None:
            self.gvar = gvar                        
            self.folder_gmo = f'{self.gvar.domain}/{self.gvar.exchange}/'  # desktop-pc/bot/        
    
        #########################
        def __str__(self) -> str:
            return f"Debug({self.gvar=}, {self.folder_gmo=})"    
        
        ###############################################     
        def print_log(self, msg: str, msg2=any) ->None:   
            msg = str(msg)  # cast string
    
            # write log to a txt file
            now = dt.datetime.now() # current date and time
            date_str = now.strftime('%Y%m%d')   # 20220912
            txt_file = self.folder_gmo + f'log({date_str}).txt' # desktop-pc/bot/log(20220912).txt
        
            # remove ESC 
            log_msg = msg.replace(Bcolors.HEADER,'').replace(Bcolors.OKBLUE,'').replace(Bcolors.OKCYAN,'')
            log_msg = log_msg.replace(Bcolors.OKGREEN,'').replace(Bcolors.WARNING,'').replace(Bcolors.FAIL,'')
            log_msg = log_msg.replace(Bcolors.ENDC,'').replace(Bcolors.BOLD,'').replace(Bcolors.UNDERLINE,'')
    
            # remoce ESC
            if msg2 != any:
                msg2 = str(msg2)    # cast msg2
                log_msg2 = msg2.replace(Bcolors.HEADER,'').replace(Bcolors.OKBLUE,'').replace(Bcolors.OKCYAN,'')
                log_msg2 = log_msg2.replace(Bcolors.OKGREEN,'').replace(Bcolors.WARNING,'').replace(Bcolors.FAIL,'')
                log_msg2 = log_msg2.replace(Bcolors.ENDC,'').replace(Bcolors.BOLD,'').replace(Bcolors.UNDERLINE,'')        
        
            # append a msg, msg2 into the log file => log(YYYYMMDD).txt
            f = open(txt_file, 'a', encoding='utf-8') 
    
            f.write(log_msg)
            if msg2 != any:
                f.write(', ' + log_msg2)
            f.write(f" [{now.strftime('%Y-%m-%d %H:%M:%S')}]")
            f.write('\n')
         
            f.close()
    
            # print a msg, msg2 to the screen
            if msg2 == any:
                print(msg, f"[{Bcolors.OKCYAN}{now.strftime('%Y-%m-%d %H:%M:%S')}{Bcolors.ENDC}]")
            else:
                print(msg, msg2, f"[{Bcolors.OKCYAN}{now.strftime('%Y-%m-%d %H:%M:%S')}{Bcolors.ENDC}]")
    
        ########################################  
        def trace_write(self, msg: str) -> None:
            if self.gvar.debug_mode:  self.print_log(msg)
    
        #######################################  
        def trace_warn(self, msg: str) -> None:
            if self.gvar.debug_mode:  self.print_log(f'{Bcolors.WARNING}{msg}{Bcolors.ENDC}')  
    
        ######################################## 
        def trace_error(self, msg: str) -> None:
            if self.gvar.debug_mode:  self.print_log(f'{Bcolors.FAIL}{msg}{Bcolors.ENDC}') 
    
        ####################################### 
        def sound_alert(self, count=1) -> None:
            duration = 1000   # milliseconds
            freq = 440  # Hz
            for i in range(count):
                winsound.Beep(freq, duration) 
                sleep(0.5)