-
This commit is contained in:
121
main.py
Normal file
121
main.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from typing import List
|
||||
|
||||
from historical_data.historical_data import historical_data_tradingview_csv
|
||||
from internal_types.types import Instrument, Position, SecurityType
|
||||
from strategy.buy_and_hold import BuyAndHold
|
||||
from strategy.sma_crossover import SMACrossover
|
||||
from strategy.strategy import Strategy
|
||||
from strategy.turtle_system_1 import TurtleSystem1
|
||||
from trading_gateway.trading_gateway import BacktestGateway, TradingGateway
|
||||
from utils.utils import (
|
||||
SEC_1_DAY,
|
||||
SEC_1_HOUR,
|
||||
SEC_15_MINUTES,
|
||||
SEC_30_MINUTES,
|
||||
log_sharpe_ratio,
|
||||
simple_sharpe_ratio,
|
||||
)
|
||||
|
||||
|
||||
def backtest(strategy: Strategy, instr: Instrument, interval_sec: int, initial_balance: float,
|
||||
drawdown_limit: float, trading_gateway: TradingGateway):
|
||||
balance_history: List[float] = []
|
||||
|
||||
for ohlc in trading_gateway.next_ohlc():
|
||||
balance = strategy.net_liquid_value(ohlc.close)
|
||||
balance_history.append(balance)
|
||||
|
||||
if balance <= initial_balance * (1 - drawdown_limit):
|
||||
break
|
||||
|
||||
strategy.process_ohlc(ohlc)
|
||||
|
||||
unfilled_pos = strategy.unfilled_positions(instr)
|
||||
if unfilled_pos.quantity:
|
||||
if not (ohlc.low <= unfilled_pos.price <= ohlc.high):
|
||||
# unfilled_pos = Position(unfilled_pos.instr, unfilled_pos.quantity, ohlc.open)
|
||||
unfilled_pos = Position(unfilled_pos.instr, unfilled_pos.quantity, ohlc.close)
|
||||
strategy.order_filled(unfilled_pos)
|
||||
|
||||
simple_sharpe = round(simple_sharpe_ratio(balance_history, interval_sec), 4)
|
||||
log_sharpe = round(log_sharpe_ratio(balance_history, interval_sec), 4)
|
||||
return_pct = round((balance_history[-1] / initial_balance - 1) * 100, 4)
|
||||
return f'simple_sharpe: {simple_sharpe}, log_sharpe: {log_sharpe}, return_pct: {return_pct}%'
|
||||
|
||||
|
||||
def backtest_turtle(csv: str, instr: Instrument, interval_sec: int, initial_balance: float,
|
||||
drawdown_limit: float, warmup_t0: str, t0: str, t1: str):
|
||||
warmup_historical_data = historical_data_tradingview_csv(csv, instr, warmup_t0, t0)
|
||||
trading_gateway: TradingGateway = BacktestGateway(csv, instr, t0, t1)
|
||||
|
||||
strategy: Strategy = TurtleSystem1(initial_balance, instr)
|
||||
strategy.warmup(warmup_historical_data)
|
||||
|
||||
return backtest(strategy, instr, interval_sec, initial_balance, drawdown_limit, trading_gateway)
|
||||
|
||||
|
||||
def backtest_buy_and_hold(csv: str, instr: Instrument, interval_sec: int, initial_balance: float,
|
||||
drawdown_limit: float, t0: str, t1: str):
|
||||
trading_gateway: TradingGateway = BacktestGateway(csv, instr, t0, t1)
|
||||
strategy: Strategy = BuyAndHold(initial_balance, instr)
|
||||
return backtest(strategy, instr, interval_sec, initial_balance, drawdown_limit, trading_gateway)
|
||||
|
||||
|
||||
def backtest_sma_crossover(csv: str, instr: Instrument, interval_sec: int, initial_balance: float,
|
||||
drawdown_limit: float, warmup_t0: str, t0: str, t1: str):
|
||||
warmup_historical_data = historical_data_tradingview_csv(csv, instr, warmup_t0, t0)
|
||||
trading_gateway: TradingGateway = BacktestGateway(csv, instr, t0, t1)
|
||||
|
||||
strategy: Strategy = SMACrossover(initial_balance, instr, interval_sec, 12 * SEC_1_HOUR,
|
||||
26 * SEC_1_HOUR)
|
||||
strategy.warmup(warmup_historical_data)
|
||||
|
||||
return backtest(strategy, instr, interval_sec, initial_balance, drawdown_limit, trading_gateway)
|
||||
|
||||
|
||||
def main():
|
||||
# csv = './csv/qqq_1999_03_10_1_day.csv'
|
||||
# csv = './csv/qqq_2023_02_01_15_min.csv'
|
||||
csv = './csv/slv_2023_01_03_30_min.csv'
|
||||
# instr = Instrument('QQQ', SecurityType.EQUITY, 1)
|
||||
instr = Instrument('SLV', SecurityType.EQUITY, 1)
|
||||
# interval_sec = SEC_15_MINUTES
|
||||
interval_sec = SEC_30_MINUTES
|
||||
# interval_sec = SEC_1_DAY
|
||||
initial_balance = 1_000_000
|
||||
drawdown_limit = 1.00 # allow 100% loss
|
||||
# warmup_t0 = '2023-02-01'
|
||||
# t0, t1 = '2023-03-15', '2026-03-01'
|
||||
# warmup_t0 = '2025-10-01'
|
||||
# t0, t1 = '2026-02-01', '2025-03-10'
|
||||
|
||||
# print(backtest_buy_and_hold(csv, instr, interval_sec, initial_balance, drawdown_limit, t0, t1))
|
||||
# print(
|
||||
# backtest_turtle(csv, instr, interval_sec, initial_balance, drawdown_limit, warmup_t0, t0, t1))
|
||||
# print(
|
||||
# backtest_sma_crossover(csv, instr, interval_sec, initial_balance, drawdown_limit, warmup_t0, t0,
|
||||
# t1))
|
||||
|
||||
for m in range(1, 12):
|
||||
warmup_t0 = '2023-02-01'
|
||||
t0, t1 = f'2025-{m:02}-01', f'2025-{m+1:02}-01'
|
||||
print(f'---- {t0} ----')
|
||||
print('buy and hold:',
|
||||
backtest_buy_and_hold(csv, instr, interval_sec, initial_balance, drawdown_limit, t0, t1))
|
||||
print(
|
||||
'12-16 SMA: ',
|
||||
backtest_sma_crossover(csv, instr, interval_sec, initial_balance, drawdown_limit, warmup_t0,
|
||||
t0, t1))
|
||||
|
||||
# for y in range(2000, 2026):
|
||||
# warmup_t0, t0, t1 = f'{y-1}-10-01', f'{y}-01-01', f'{y+1}-01-01'
|
||||
# print(f'---- {y} ----')
|
||||
# print('buy and hold:',
|
||||
# backtest_buy_and_hold(csv, instr, interval_sec, initial_balance, drawdown_limit, t0, t1))
|
||||
# print(
|
||||
# 'turtle :',
|
||||
# backtest_turtle(csv, instr, interval_sec, initial_balance, drawdown_limit, warmup_t0, t0, t1))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user