Scenario 1: bt_gw_fx_orca_gu_3_m5.ipynb (รันผ่าน Jupyter Notebook)

<< กลับไปหน้า Backtesting Examples & Workshops

<< กลับไปหน้า Backtesting Setting Description

รูปแบบการรัน backtest สำหรับ scenario นี้คือ

  • backtest 1 โมเดล
  • predict signal โดยใช้ rule based
  • predict SL, TP, pos. size โดยใช้ rule based

Guideline

  • การรัน backtest โมเดลจริงที่ไม่ใช่ในเวิร์กช็อป ควรรันผ่าน Command Prompt หรือ Terminal เสมอ เพราะ ระหว่างการรันอาจมีการ print log จำนวนมาก หากรันบนเว็บเบราเซอร์อาจทำให้เกิดปัญหาหน่วยความจำเต็ม (เพราะเว็บเบราเซอร์ทั่วไปมีการจำกัดปริมาณการใช้หน่วยความจำไว้) หรือเมื่อ save ไฟล์ .ipynb แล้วพอจะเปิดใหม่อาจเปิดไม่ขึ้น แล้วเจอ error เพราะตอน save ไฟล์ ได้ save พวกข้อความ log จำนวนมากไปด้วย ทำให้ไฟล์มีขนาดใหญ่มาก จึงอาจเปิดไม่ขึ้น
  • ปัจจัยที่มีผลต่อปริมาณ log คือ 1) พวกค่า backtest setting ที่เกี่ยวกับ log 2) ปริมาณแท่งราคาที่ใช้ ซึ่งเกี่ยวกับค่า backtest setting ที่เกี่ยวกับช่วงวันที่จะ backtest
  • ตอนเริ่มรันหากพบข้อความ Warning ไม่ต้องตกใจ ^^ เป็นปัญหาจุกจิกของ Python หากไม่ขึ้น error ถือว่าโอเค
  • ตอนเริ่มรันอาจใช้เวลานานมาก เพราะระบบ backtesting จะเตรียมข้อมูลและเซ็ตค่าต่างๆ ก่อนเริ่มต้น backtest model ปัจจัยสำคัญที่ส่งผลต่อความเร็ว/ช้า คือ ขนาดไฟล์ราคาที่ใช้

Workshop

1) Prepare

  1. ดาวน์โหลดไฟล์ workshop_backtest_1.zip (click me please) (หากดาวน์โหลดมาแล้ว ไม่ต้องโหลดอีก) จากนั้น extract ไฟล์ข้างบน จะได้โฟลเดอร์นอกสุดชื่อ DeepQuantProjects
  2. เปิดหน้าต่าง Command Prompt (Windows) หรือ Terminal (Mac OS / Linux) แล้วเข้าไปในโฟลเดอร์ DeepQuantProjects/labs/backtest แล้วให้เข้า virtual environment ชื่อ deepquant_env แล้วรันคำสั่ง pip install -r requirements.txt เพื่อ install แพ็กเกจของ deepquant (หากทำขั้นตอนนี้แล้วไม่ต้องทำอีก)
  3. ใช้หน้าต่าง Command Prompt (Windows) หรือ Terminal (Mac OS / Linux) เดิม แล้วรันคำสั่ง jupyter notebook (หากรัน Jupyter Notebook แล้ว ไม่ต้องรันใหม่อีก) จากนั้นระบบจะเปิดหน้าต่างเว็บเบราเซอร์อัตโนมัติ หรือจะเปิดเว็บเบราเซอร์ที่ชอบใช้เองก็ได้

2) Run backtest

  1. บนเว็บเบราเซอร์ที่ใช้ ให้เข้าไปที่โฟลเดอร์ DeepQuantProjects/labs/backtest/FX แล้วเปิดไฟล์ที่ชื่อ bt_gw_fx_orca_gu_3_m5.ipynb
  2. เปิดหน้าต่าง Command Prompt หรือ Terminal หน้าต่างใหม่ แล้วเข้า virtual environment ชื่อ deepquant_env จากนั้นเข้าไปที่โฟลเดอร์ DeepQuantProjects/labs/backtest แล้วรันคำสั่ง python plot_eq.py FX gw_fx จะ pop up หน้าต่างโล่งๆ ขึ้นมา เมื่อเริ่มรัน backtest ให้มาดูที่หน้าต่างนี้จะเห็นค่า real time equity ระหว่างกำลังรัน backtest
  3. รันโค้ดชุดนี้ (บางไฟล์ในเวิร์กช็อปชุด backtest อาจรันนานมากกกก เพราะใช้ไฟล์ข้อมูลราคามีความยาว 20 ปี หากรอไม่ไหว ให้เปิดไฟล์ราคาด้วย notepad หรือ text editor แล้วลบข้อมูลเก่าๆ ทิ้งเองได้ครับ)
  4. เมื่อรัน backtest เสร็จแล้วจะเห็น backtest report ใน output cell ซึ่งจะแสดงผลต่อท้าย backtest log นอกจากนี้ระบบ backtesting ยัง save ไฟล์ backtest report ชื่อ backtest_report_[strategy name].html เช่น backtest_report_gw_fx.html เก็บไว้ในโฟลเดอร์ DeepQuantProjects/labs/backtest/reports สามารถเปิดดูในเว็บเบราเซอร์ได้
  5. ลองเปิดโค้ด trade model ดูรายละเอียดโค้ด Python ได้ ไฟล์ชื่อ orca_gu_3.py อยู่ในโฟลเดอร์ DeepQuantProjects/labs/backtest/FX/models

Exercise

  1. ลองแก้ไขค่า config['log_enable'] เป็นค่า False แล้วรันใหม่ แล้วลองแก้กลับเป็นค่า True แล้วรันใหม่ สังเกตผล log ที่แตกต่างกัน
  2. ลองแก้ไขค่า config['trade_log_interval'] เป็นค่า 20 แล้วรันใหม่ แล้วลองแก้กลับเป็นค่า 10 แล้วรันใหม่ สังเกตผล log ที่แตกต่างกัน
  3. ลองแก้ไขค่า config['always_cal_indi'] เป็นค่า False แล้วรันใหม่ แล้วลองแก้กลับเป็นค่า True แล้วรันใหม่ สังเกตความเร็วตอนรัน backtest ที่แตกต่างกัน แล้วลองเปิด Tab ใหม่บนเว็บเบราเซอร์ แล้วเข้าไปในโฟลเดอร์ /labs/backtest/FX/datasets จะเห็นว่ามีไฟล์ชื่อ dataset_indi_orca_gu_3.csv ลองคลิ้กเปิดไฟล์นี้ หรือเปิดด้วย notepad หรือ text editor ดูครับ (ไฟล์อาจมีขนาดใหญ่มาก จนเปิดไม่ได้ ระวังจุดนี้นะครับ) ไฟล์นี้คือการทำ caching ข้อมูลที่ถูกคำนวณสร้าง indicators กับ features แล้ว หากการรัน backtest ครั้งต่อๆ ไป โดยไม่ได้ไปแก้โค้ดคำนวณสร้าง indicators กับ features ให้เซ็ตค่า always_cal_indi เป็น False ตอนรัน backtest จะใช้ dataset จากไฟล์นี้เลย ไม่เสียเวลาคำนวณใหม่
  4. ลองแก้ไขค่า config['bar_details_save_enable'] เป็นค่า True แล้วรันใหม่ รอจนรันเสร็จ แล้วให้เข้าไปในโฟลเดอร์ /labs/backtest/FX/datasets จะเห็นว่ามีไฟล์ชื่อ orca_gu_3_bars.csv เกิดขึ้น เป็นไฟล์เก็บรายละเอียดเทรดและสถิติของเทรดที่มี position ในทุกแท่งราคา (active trades) จากนั้นให้แก้ค่ากลับเป็น False ให้เหมือนเดิม
  5. ลองแก้ไขค่า config['trade_details_save_enable'] เป็นค่า True แล้วรันใหม่ รอจนรันเสร็จ แล้วให้เข้าไปในโฟลเดอร์ /labs/backtest/FX/datasets จะเห็นว่ามีไฟล์ชื่อ orca_gu_3_trades.csv เกิดขึ้น เป็นไฟล์เก็บรายละเอียดเทรดและสถิติของเทรดที่ปิด position แล้ว (historical trades) จากนั้นให้แก้ค่ากลับเป็น False ให้เหมือนเดิม
  6. ลองแก้ไขค่า log_enable ใน config['ms_config'] เป็นค่า True แล้วรันใหม่ แล้วลองแก้กลับเป็นค่า False แล้วรันใหม่ สังเกตผล log ที่แตกต่างกัน

Backtesting Code

pattern ในการตั้งชื่อไฟล์ backtest คือ bt_[strategy name]_[trade model name]_[number]_[timeframe].py หรือ .ipynb หรือจะตั้งชื่ออื่นที่ชอบเองก็ได้ครับ

สีในโค้ดด้านล่าง

  • background สีเทา หมายถึง เป็นโค้ดที่ไม่ได้ใช้
  • background สีส้ม หมายถึง โค้ดที่เกี่ยวกับกลไก backtesting
  • ตัวอักษรหนาและมีสีน้ำเงิน หมายถึง โค้ด setting ที่ต้องเซ็ตให้ถูกต้องทุกครั้ง
  • ตัวอักษรหนาและมีสีแดง หมายถึง โค้ด setting ที่จำเป็นของ trade model นั้นๆ ต้องเซ็ตให้เหมาะกับโมเดลของตัวเอง และให้เหมาะกับสินค้าและตลาดที่จะเทรด
import os
import yaml
import importlib

import sys
sys.path.append("../")

from deepquant.backtest.backtest_sim import BacktestEngine

dqif_path = "../../DQIF"


# =================================================================================
# BEGIN: Backtest configuration
# =================================================================================
config = {}
config['broker'] = 'Exness' # name of broker or exchange or '' of not use. For SET (equity & TFEX) uses ''
config['strategy_name'] = 'gw_fx' # name of strategy robot
config['log_enable'] = True
config['initial_equity'] = 10000
config['from_date'] = '2022-07-01' # format is 'YYYY-mm-dd', e.g. 2021-12-31
config['to_date'] = '2023-01-31' # format is 'YYYY-mm-dd', e.g. 2021-12-31
config['timeframe'] = 'M5'
config['market'] = 'FX' # FX, CRYPTO, TFEX, EQUITY, USA *EQUITY is Thai stock market
config['account_type'] = '' # '' for FX, SPOT or FUTURES for CRYPTO, EQUITY or TFEX for SET, EQUITY or FUTURES for USA
config['leverage'] = 0 # example 25 = 25%, NOTE: for CRYPTO-FUTURES only
config['reserve_fund'] = 0

# print log of model and update model-portfolio equity file every N trade, for example 100 = 100 trades
config['trade_log_interval'] = 10

config['trade_model_module_path'] = "models"

config['price_files'] = [
    {
        'symbol_name': 'GBPUSD'
        , 'price_file': f"../../../datasets/{config['market']}/GBPUSD_M5.csv" # path of price file
    }
]

# BEGIN: models config (DO NOT REMOVE THIS COMMENT)
config['models'] = [
    {
        'model_name': 'orca_gu_3'
        , 'symbol_name' : 'GBPUSD'
        , 'trade_model_module' : "orca_gu_3"
        , 'trade_model_class' : "TradeModel_Orca_GU_3"
        , 'model_names': [None, None, None]
        , 'fund_allocate_size' : 1.0
        , 'strategy_config' : { # this field must be added to each trading robot in robot_config.yaml
                'sltp_mode' : 2 # 1=point, 2=price percentage
                #, 'list_sl' : [0.004, 0.006, 0.008, 0.01, 0.012, 0.015] # 0.02 = 2%
                #, 'list_tp' : [0.002, 0.004, 0.006, 0.009, 0.012] # 0.02 = 2%
                #, 'list_ps' : [0.2, 1, 2.5, 3.5] # 20 = 20% !!!!!!
                #, 'rr_min' : 1 # min risk/reward ratio calculate by sl/tp
                #, 'rr_max' : 3 # max risk/reward ratio calculate by sl/tp
                #, 'pssl_max' : 0.025 # max limit of ps * sl, if max sl is 0.04, max ps is 5, ps*sl = 0.04 * 5
                #, 'hold_bars_limit' : 900
                , 'max_ruin' : 0.8 # accepted max ruin, example: 0.5=50%, NOT check if config['models'] > 1 model
                , 'max_dd' : 0.8 # accepted max drawdown, example: 0.5=50%, NOT check if config['models'] > 1 model
                , 'default_pos_size' : 0.01 # for fixed position size
                , 'pos_size_type' : 2 # 1=use 'default_pos_size', 2=use dynamic pos. size calculation
                , 'min_pos_size' : 0.01 # minimum position size
                , 'pos_size_limit' : -1 # -1=no limit
                , 'pos_size_decimal_num' : 2
                , 'cal_pos_size_formula' : 2 # Required field
                , 'trade_position' : 3 # 1=buy/long, 2=sell/short, 3=long & short
                , 'point_value' : 1 # unit depends symbol or market
                , 'stop_loss_point' : None
                , 'risk' : None # example 3 = 3%
        }
        , 'trade_stats_config' : {}
        , 'backtest_config' : {
                'derivatives_mode': True
                , 'commission_type': 1 # 1=money, 2=percentage
                , 'commission_amount': 20 # N USD/1 unit or N %/1 unit
                , 'max_slippage': {'freq1':3, 'freq2':6, 'freq3': 10, 'freq4': 15}
        }
    }
]

config['rl_models'] = {}
# END: models config (DO NOT REMOVE THIS COMMENT)

# =================================================================================

config['always_cal_indi'] = True # False=calculate once, True=calculate every running
config['cal_stats_every_hold_bars'] = False # True=calculate trade stats every bars with holding position, False=calculate at exit bar only

#config['process_hold_bars'] = False # True=will process scale in/out, trailing stop, modify SL/TP, False=will only check SL/TP
config['bar_details_save_enable'] = False # Append every bars of each models to csv file (SUPER VERY SLOWWWWWWWW !!!!!!)
config['trade_details_save_enable'] = False # Append every trades of each models to csv file (VERY SLOWWWWWWWW !!!!!!)

config['ms_config'] = {
        'log_enable' : False # True or False
        , 'round_log_interval' : 0.1 # print log of master process and update portfolio equity file every N% of total rows of running schedule, for example 0.1 = 0.1%
        , 'single_worker_mode' : 'loop' # 'async' or 'loop', running mode for backtest only one model
        , 'async_host' : 'localhost'
        , 'async_port' : 6379 #4788
    }

config['rl_model_path'] = f'../../../dockers/deepquant_mlserve/ml_models/{config["market"]}/models'
config['report_path'] = f"./reports"
# Path to save dataset file after calculated indicators and features. Can change path.
config['dataset_path'] = f"./datasets"
config['equity_file_path'] = f"./datasets"
config['ml_model_url'] = 'http://127.0.0.1:5000/ml'

if config["broker"] != '':
    symbol_config_file = f'../../common/symbol_config_{config["market"].lower()}_{config["broker"].lower()}.yaml'
else:
    symbol_config_file = f'../common/symbol_config_{config["market"].lower()}.yaml'
config['symbols'] = yaml.safe_load(open(symbol_config_file))

# =================================================================================
# END Backtest configuration
# =================================================================================


# Copy trade models and indi helpers from DQIF to /backtest/<market>/models
cur_work_dir = os.getcwd()
if '\\' in cur_work_dir:
    cur_work_dir = cur_work_dir.replace('\\', '/')
sys.path.append(cur_work_dir.replace(f"backtest/{config['market']}", 'common'))
print(sys.path)
model_prep = importlib.import_module('model_prep')
ml_models = model_prep.preproc(config, 'backtest')

# Process actions
trade_models = BacktestEngine.build_trade_models(config)
config['run_file'] = f"{os.getcwd()}/bt_gw_fx_orca_gu_3_m5.ipynb"

def main():
    # Start process engine
    bt = BacktestEngine()
    bt.start(config, trade_models, ml_models, output_type=2)

main()

Leave a Reply

Discover more from

Subscribe now to keep reading and get access to the full archive.

Continue reading