using configuration file
This commit is contained in:
parent
200a1bf307
commit
671422976d
33
configuration/crypto.cfg
Normal file
33
configuration/crypto.cfg
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"security_type": "CRYPTO",
|
||||||
|
"data_directory": "./data/crypto",
|
||||||
|
"datafiles": [
|
||||||
|
"20250519.mktdata.ohlcv.db"
|
||||||
|
],
|
||||||
|
"db_table_name": "bnbspot_ohlcv_1min",
|
||||||
|
"exchange_id": "BNBSPOT",
|
||||||
|
"instrument_id_pfx": "PAIR-",
|
||||||
|
"instruments": [
|
||||||
|
"BTC-USDT",
|
||||||
|
"BCH-USDT",
|
||||||
|
"ETH-USDT",
|
||||||
|
"LTC-USDT",
|
||||||
|
"XRP-USDT",
|
||||||
|
"ADA-USDT",
|
||||||
|
"SOL-USDT",
|
||||||
|
"DOT-USDT"
|
||||||
|
],
|
||||||
|
"trading_hours": {
|
||||||
|
"begin_session": "00:00:00",
|
||||||
|
"end_session": "23:59:00",
|
||||||
|
"timezone": "UTC"
|
||||||
|
},
|
||||||
|
"price_column": "close",
|
||||||
|
"min_required_points": 30,
|
||||||
|
"zero_threshold": 1e-10,
|
||||||
|
"dis-equilibrium_open_trshld": 2.0,
|
||||||
|
"dis-equilibrium_close_trshld": 0.5,
|
||||||
|
"training_minutes": 120,
|
||||||
|
"funding_per_pair": 2000.0,
|
||||||
|
"strategy_class": "strategies.StaticFitStrategy"
|
||||||
|
}
|
||||||
35
configuration/equity.cfg
Normal file
35
configuration/equity.cfg
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"security_type": "EQUITY",
|
||||||
|
"data_directory": "./data/equity",
|
||||||
|
"datafiles": [
|
||||||
|
# "20250508.alpaca_sim_md.db",
|
||||||
|
"20250509.alpaca_sim_md.db",
|
||||||
|
# "20250512.alpaca_sim_md.db",
|
||||||
|
# "20250513.alpaca_sim_md.db",
|
||||||
|
# "20250514.alpaca_sim_md.db",
|
||||||
|
# "20250515.alpaca_sim_md.db",
|
||||||
|
# "20250516.alpaca_sim_md.db",
|
||||||
|
# "20250519.alpaca_sim_md.db",
|
||||||
|
# "20250520.alpaca_sim_md.db"
|
||||||
|
],
|
||||||
|
"db_table_name": "md_1min_bars",
|
||||||
|
"exchange_id": "ALPACA",
|
||||||
|
"instrument_id_pfx": "STOCK-",
|
||||||
|
"instruments": [
|
||||||
|
"COIN",
|
||||||
|
"GBTC"
|
||||||
|
],
|
||||||
|
"trading_hours": {
|
||||||
|
"begin_session": "9:30:00",
|
||||||
|
"end_session": "16:00:00",
|
||||||
|
"timezone": "America/New_York"
|
||||||
|
},
|
||||||
|
"price_column": "close",
|
||||||
|
"min_required_points": 30,
|
||||||
|
"zero_threshold": 1e-10,
|
||||||
|
"dis-equilibrium_open_trshld": 2.0,
|
||||||
|
"dis-equilibrium_close_trshld": 1.0,
|
||||||
|
"training_minutes": 120,
|
||||||
|
"funding_per_pair": 2000.0,
|
||||||
|
"strategy_class": "strategies.StaticFitStrategy"
|
||||||
|
}
|
||||||
1
prompts/20250612.testing_code_request.txt
Normal file
1
prompts/20250612.testing_code_request.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Create python code that tests pairs trading strategy
|
||||||
28
scripts/load_crypto_1min.sh
Executable file
28
scripts/load_crypto_1min.sh
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# -------------------------------------
|
||||||
|
# --- Given month, specific dates
|
||||||
|
# -------------------------------------
|
||||||
|
|
||||||
|
# for dt in 20250528 20250529 20250530 20250531; do
|
||||||
|
# rsync -ahvv cvtt@hs01.cvtt.vpn:/works/cvtt/md_archive/crypto/sim/2025/2025-05/${dt}.*.gz ./
|
||||||
|
# done
|
||||||
|
# -------------------------------------
|
||||||
|
|
||||||
|
# -------------------------------------
|
||||||
|
# --- Current month - all files
|
||||||
|
# -------------------------------------
|
||||||
|
pushd ./data/crypto
|
||||||
|
rsync -ahvv cvtt@hs01.cvtt.vpn:/works/cvtt/md_archive/crypto/sim/*.gz ./
|
||||||
|
# -------------------------------------
|
||||||
|
|
||||||
|
for srcfname in $(ls *.db.gz); do
|
||||||
|
dt="${srcfname:0:8}"
|
||||||
|
tgtfile=${dt}.mktdata.ohlcv.db
|
||||||
|
echo "${srcfname} -> ${tgtfile}"
|
||||||
|
|
||||||
|
gunzip -c $srcfname > temp.db
|
||||||
|
rm -f ${tgtfile} && sqlite3 temp.db ".dump md_1min_bars" | sqlite3 ${tgtfile} && rm ${srcfname}
|
||||||
|
done
|
||||||
|
rm temp.db
|
||||||
|
popd
|
||||||
File diff suppressed because one or more lines are too long
@ -1,3 +1,6 @@
|
|||||||
|
import argparse
|
||||||
|
import hjson
|
||||||
|
import importlib
|
||||||
|
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
@ -9,106 +12,15 @@ from tools.trading_pair import TradingPair
|
|||||||
from results import BacktestResult
|
from results import BacktestResult
|
||||||
|
|
||||||
|
|
||||||
# ------------------------ Configuration ------------------------
|
def load_config(config_path: str) -> Dict:
|
||||||
# Default configuration
|
with open(config_path, "r") as f:
|
||||||
CRYPTO_CONFIG: Dict = {
|
config = hjson.load(f)
|
||||||
"security_type": "CRYPTO",
|
return config
|
||||||
# --- Data retrieval
|
|
||||||
"data_directory": "./data/crypto",
|
|
||||||
"datafiles": [
|
|
||||||
"20250519.mktdata.ohlcv.db",
|
|
||||||
# "20250520.mktdata.ohlcv.db",
|
|
||||||
# "20250521.mktdata.ohlcv.db",
|
|
||||||
# "20250522.mktdata.ohlcv.db",
|
|
||||||
# "20250523.mktdata.ohlcv.db",
|
|
||||||
# "20250524.mktdata.ohlcv.db",
|
|
||||||
# "20250525.mktdata.ohlcv.db",
|
|
||||||
],
|
|
||||||
"db_table_name": "bnbspot_ohlcv_1min",
|
|
||||||
# ----- Instruments
|
|
||||||
"exchange_id": "BNBSPOT",
|
|
||||||
"instrument_id_pfx": "PAIR-",
|
|
||||||
"instruments": [
|
|
||||||
"BTC-USDT",
|
|
||||||
"BCH-USDT",
|
|
||||||
"ETH-USDT",
|
|
||||||
"LTC-USDT",
|
|
||||||
"XRP-USDT",
|
|
||||||
"ADA-USDT",
|
|
||||||
"SOL-USDT",
|
|
||||||
"DOT-USDT",
|
|
||||||
],
|
|
||||||
"trading_hours": {
|
|
||||||
"begin_session": "00:00:00",
|
|
||||||
"end_session": "23:59:00",
|
|
||||||
"timezone": "UTC",
|
|
||||||
},
|
|
||||||
# ----- Model Settings
|
|
||||||
"price_column": "close",
|
|
||||||
"min_required_points": 30,
|
|
||||||
"zero_threshold": 1e-10,
|
|
||||||
|
|
||||||
"dis-equilibrium_open_trshld": 2.0,
|
|
||||||
"dis-equilibrium_close_trshld": 0.5,
|
|
||||||
|
|
||||||
# "training_minutes": 120,
|
|
||||||
"training_minutes": 120,
|
|
||||||
# ----- Validation
|
|
||||||
"funding_per_pair": 2000.0, # USD
|
|
||||||
}
|
|
||||||
|
|
||||||
# ========================== EQUITIES
|
|
||||||
EQT_CONFIG: Dict = {
|
|
||||||
# --- Data retrieval
|
|
||||||
"security_type": "EQUITY",
|
|
||||||
"data_directory": "./data/equity",
|
|
||||||
"datafiles": [
|
|
||||||
# "20250508.alpaca_sim_md.db",
|
|
||||||
"20250509.alpaca_sim_md.db",
|
|
||||||
# "20250512.alpaca_sim_md.db",
|
|
||||||
# "20250513.alpaca_sim_md.db",
|
|
||||||
# "20250514.alpaca_sim_md.db",
|
|
||||||
# "20250515.alpaca_sim_md.db",
|
|
||||||
# "20250516.alpaca_sim_md.db",
|
|
||||||
# "20250519.alpaca_sim_md.db",
|
|
||||||
# "20250520.alpaca_sim_md.db"
|
|
||||||
],
|
|
||||||
"db_table_name": "md_1min_bars",
|
|
||||||
# ----- Instruments
|
|
||||||
"exchange_id": "ALPACA",
|
|
||||||
"instrument_id_pfx": "STOCK-",
|
|
||||||
"instruments": [
|
|
||||||
"COIN",
|
|
||||||
"GBTC",
|
|
||||||
# "HOOD",
|
|
||||||
# "MSTR",
|
|
||||||
# "PYPL",
|
|
||||||
],
|
|
||||||
"trading_hours": {
|
|
||||||
"begin_session": "9:30:00",
|
|
||||||
"end_session": "16:00:00",
|
|
||||||
"timezone": "America/New_York",
|
|
||||||
},
|
|
||||||
# ----- Model Settings
|
|
||||||
"price_column": "close",
|
|
||||||
"min_required_points": 30,
|
|
||||||
"zero_threshold": 1e-10,
|
|
||||||
"dis-equilibrium_open_trshld": 2.0,
|
|
||||||
"dis-equilibrium_close_trshld": 1.0, #0.5,
|
|
||||||
"training_minutes": 120,
|
|
||||||
# ----- Validation
|
|
||||||
"funding_per_pair": 2000.0,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# CONFIG = CRYPTO_CONFIG
|
def run_all_pairs(
|
||||||
CONFIG = EQT_CONFIG
|
config: Dict, datafile: str, price_column: str, bt_result: BacktestResult, strategy
|
||||||
STRATEGY = StaticFitStrategy()
|
) -> None:
|
||||||
|
|
||||||
# CONFIG = CRYPTO_CONFIG
|
|
||||||
# STRATEGY = SlidingFitStrategy()
|
|
||||||
|
|
||||||
def run_all_pairs(config: Dict, datafile: str, price_column: str, bt_result: BacktestResult) -> None:
|
|
||||||
|
|
||||||
def _create_pairs(config: Dict) -> List[TradingPair]:
|
def _create_pairs(config: Dict) -> List[TradingPair]:
|
||||||
nonlocal datafile
|
nonlocal datafile
|
||||||
@ -117,7 +29,7 @@ def run_all_pairs(config: Dict, datafile: str, price_column: str, bt_result: Bac
|
|||||||
unique_index_pairs = [(i, j) for i in all_indexes for j in all_indexes if i < j]
|
unique_index_pairs = [(i, j) for i in all_indexes for j in all_indexes if i < j]
|
||||||
pairs = []
|
pairs = []
|
||||||
market_data_df = load_market_data(
|
market_data_df = load_market_data(
|
||||||
f'{config["data_directory"]}/{datafile}', config=CONFIG
|
f'{config["data_directory"]}/{datafile}', config=config
|
||||||
)
|
)
|
||||||
for a_index, b_index in unique_index_pairs:
|
for a_index, b_index in unique_index_pairs:
|
||||||
pair = TradingPair(
|
pair = TradingPair(
|
||||||
@ -129,10 +41,11 @@ def run_all_pairs(config: Dict, datafile: str, price_column: str, bt_result: Bac
|
|||||||
pairs.append(pair)
|
pairs.append(pair)
|
||||||
return pairs
|
return pairs
|
||||||
|
|
||||||
|
|
||||||
pairs_trades = []
|
pairs_trades = []
|
||||||
for pair in _create_pairs(config):
|
for pair in _create_pairs(config):
|
||||||
single_pair_trades = STRATEGY.run_pair(pair=pair, config=CONFIG, bt_result=bt_result)
|
single_pair_trades = strategy.run_pair(
|
||||||
|
pair=pair, config=config, bt_result=bt_result
|
||||||
|
)
|
||||||
if single_pair_trades is not None and len(single_pair_trades) > 0:
|
if single_pair_trades is not None and len(single_pair_trades) > 0:
|
||||||
pairs_trades.append(single_pair_trades)
|
pairs_trades.append(single_pair_trades)
|
||||||
# Check if result_list has any data before concatenating
|
# Check if result_list has any data before concatenating
|
||||||
@ -149,12 +62,24 @@ def run_all_pairs(config: Dict, datafile: str, price_column: str, bt_result: Bac
|
|||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser(description="Run pairs trading backtest.")
|
||||||
|
parser.add_argument(
|
||||||
|
"--config", type=str, required=True, help="Path to the configuration file."
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
CONFIG = load_config(args.config)
|
||||||
|
|
||||||
|
# Dynamically instantiate strategy class
|
||||||
|
strategy_class_name = CONFIG.get("strategy_class", "strategies.StaticFitStrategy")
|
||||||
|
module_name, class_name = strategy_class_name.rsplit(".", 1)
|
||||||
|
module = importlib.import_module(module_name)
|
||||||
|
STRATEGY = getattr(module, class_name)()
|
||||||
|
|
||||||
# Initialize a dictionary to store all trade results
|
# Initialize a dictionary to store all trade results
|
||||||
all_results: Dict[str, Dict[str, Any]] = {}
|
all_results: Dict[str, Dict[str, Any]] = {}
|
||||||
bt_results = BacktestResult(config=CONFIG)
|
bt_results = BacktestResult(config=CONFIG)
|
||||||
|
|
||||||
# Initialize global PnL tracking variables
|
|
||||||
|
|
||||||
# Process each data file
|
# Process each data file
|
||||||
price_column = CONFIG["price_column"]
|
price_column = CONFIG["price_column"]
|
||||||
for datafile in CONFIG["datafiles"]:
|
for datafile in CONFIG["datafiles"]:
|
||||||
@ -166,7 +91,11 @@ def main() -> None:
|
|||||||
# Process data for this file
|
# Process data for this file
|
||||||
try:
|
try:
|
||||||
run_all_pairs(
|
run_all_pairs(
|
||||||
config=CONFIG, datafile=datafile, price_column=price_column, bt_result=bt_results
|
config=CONFIG,
|
||||||
|
datafile=datafile,
|
||||||
|
price_column=price_column,
|
||||||
|
bt_result=bt_results,
|
||||||
|
strategy=STRATEGY,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Store results with file name as key
|
# Store results with file name as key
|
||||||
@ -175,17 +104,14 @@ def main() -> None:
|
|||||||
|
|
||||||
print(f"Successfully processed {filename}")
|
print(f"Successfully processed {filename}")
|
||||||
|
|
||||||
# No longer printing unrealized PnL since we removed that functionality
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error processing {datafile}: {str(e)}")
|
print(f"Error processing {datafile}: {str(e)}")
|
||||||
|
|
||||||
# BacktestResults.print_results_summary(all_results)
|
# Calculate and print results
|
||||||
bt_results.calculate_returns(all_results)
|
bt_results.calculate_returns(all_results)
|
||||||
|
|
||||||
# Print grand totals
|
|
||||||
bt_results.print_grand_totals()
|
bt_results.print_grand_totals()
|
||||||
bt_results.print_outstanding_positions()
|
bt_results.print_outstanding_positions()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
Loading…
x
Reference in New Issue
Block a user