<< กลับไปหน้า Backtesting Examples & Workshops
<< กลับไปหน้า Backtesting Setting Description
รูปแบบการรัน backtest สำหรับ scenario นี้คือ
Guideline
Workshop
1) Prepare
workshop_backtest_1.zip (click me please) (หากดาวน์โหลดมาแล้ว ไม่ต้องโหลดอีก) จากนั้น extract ไฟล์ข้างบน จะได้โฟลเดอร์นอกสุดชื่อ DeepQuantProjectsDeepQuantProjects/labs/backtest แล้วให้เข้า virtual environment ชื่อ deepquant_env แล้วรันคำสั่ง pip install -r requirements.txt เพื่อ install แพ็กเกจของ deepquant (หากทำขั้นตอนนี้แล้วไม่ต้องทำอีก)jupyter notebook (หากรัน Jupyter Notebook แล้ว ไม่ต้องรันใหม่อีก) จากนั้นระบบจะเปิดหน้าต่างเว็บเบราเซอร์อัตโนมัติ หรือจะเปิดเว็บเบราเซอร์ที่ชอบใช้เองก็ได้2) Run backtest
DeepQuantProjects/labs/backtest/FX แล้วเปิดไฟล์ที่ชื่อ bt_gw_fx_orca_gu_3_m5.ipynbDeepQuantProjects/labs/backtest แล้วรันคำสั่ง python plot_eq.py FX gw_fx จะ pop up หน้าต่างโล่งๆ ขึ้นมา เมื่อเริ่มรัน backtest ให้มาดูที่หน้าต่างนี้จะเห็นค่า real time equity ระหว่างกำลังรัน backtestbacktest_report_[strategy name].html เช่น backtest_report_gw_fx.html เก็บไว้ในโฟลเดอร์ DeepQuantProjects/labs/backtest/reports สามารถเปิดดูในเว็บเบราเซอร์ได้orca_gu_3.py อยู่ในโฟลเดอร์ DeepQuantProjects/labs/backtest/FX/modelsExercise
config['log_enable'] เป็นค่า False แล้วรันใหม่ แล้วลองแก้กลับเป็นค่า True แล้วรันใหม่ สังเกตผล log ที่แตกต่างกันconfig['trade_log_interval'] เป็นค่า 20 แล้วรันใหม่ แล้วลองแก้กลับเป็นค่า 10 แล้วรันใหม่ สังเกตผล log ที่แตกต่างกัน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 จากไฟล์นี้เลย ไม่เสียเวลาคำนวณใหม่config['bar_details_save_enable'] เป็นค่า True แล้วรันใหม่ รอจนรันเสร็จ แล้วให้เข้าไปในโฟลเดอร์ /labs/backtest/FX/datasets จะเห็นว่ามีไฟล์ชื่อ orca_gu_3_bars.csv เกิดขึ้น เป็นไฟล์เก็บรายละเอียดเทรดและสถิติของเทรดที่มี position ในทุกแท่งราคา (active trades) จากนั้นให้แก้ค่ากลับเป็น False ให้เหมือนเดิมconfig['trade_details_save_enable'] เป็นค่า True แล้วรันใหม่ รอจนรันเสร็จ แล้วให้เข้าไปในโฟลเดอร์ /labs/backtest/FX/datasets จะเห็นว่ามีไฟล์ชื่อ orca_gu_3_trades.csv เกิดขึ้น เป็นไฟล์เก็บรายละเอียดเทรดและสถิติของเทรดที่ปิด position แล้ว (historical trades) จากนั้นให้แก้ค่ากลับเป็น False ให้เหมือนเดิมlog_enable ใน config['ms_config'] เป็นค่า True แล้วรันใหม่ แล้วลองแก้กลับเป็นค่า False แล้วรันใหม่ สังเกตผล log ที่แตกต่างกันBacktesting Code
pattern ในการตั้งชื่อไฟล์ backtest คือ bt_[strategy name]_[trade model name]_[number]_[timeframe].py หรือ .ipynb หรือจะตั้งชื่ออื่นที่ชอบเองก็ได้ครับ
สีในโค้ดด้านล่าง
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()