timezone converting added
This commit is contained in:
parent
eda31d01fd
commit
0d0dde897d
@ -16,8 +16,44 @@ UNSET_INT: int = sys.maxsize
|
|||||||
|
|
||||||
# ------------------------ Configuration ------------------------
|
# ------------------------ Configuration ------------------------
|
||||||
# Default configuration
|
# Default configuration
|
||||||
CONFIG: Dict = {
|
CRYPTO_CONFIG: Dict = {
|
||||||
"exchange_id": "ALPACA",
|
# --- Data retrieval
|
||||||
|
"data_directory": "./data/crypto",
|
||||||
|
"datafiles": [
|
||||||
|
"20250519.mktdata.ohlcv.db",
|
||||||
|
],
|
||||||
|
"db_table_name": "bnbspot_ohlcv_1min",
|
||||||
|
|
||||||
|
# ----- Instruments
|
||||||
|
"exchange_id": "BNBSPOT",
|
||||||
|
"instrument_id_pfx": "PAIR-",
|
||||||
|
|
||||||
|
"instruments": [
|
||||||
|
"BTC-USDT",
|
||||||
|
"ETH-USDT",
|
||||||
|
"LTC-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,
|
||||||
|
"equilibrium_threshold_open": 5.0,
|
||||||
|
"equilibrium_threshold_close": 1.0,
|
||||||
|
"training_minutes": 120,
|
||||||
|
|
||||||
|
# ----- Validation
|
||||||
|
"funding_per_pair": 2000.0, # USD
|
||||||
|
}
|
||||||
|
# ========================== EQUITIES
|
||||||
|
EQT_CONFIG: Dict = {
|
||||||
|
# --- Data retrieval
|
||||||
"data_directory": "./data/equity",
|
"data_directory": "./data/equity",
|
||||||
"datafiles": [
|
"datafiles": [
|
||||||
"20250508.alpaca_sim_md.db",
|
"20250508.alpaca_sim_md.db",
|
||||||
@ -30,6 +66,12 @@ CONFIG: Dict = {
|
|||||||
# "20250519.alpaca_sim_md.db",
|
# "20250519.alpaca_sim_md.db",
|
||||||
# "20250520.alpaca_sim_md.db"
|
# "20250520.alpaca_sim_md.db"
|
||||||
],
|
],
|
||||||
|
"db_table_name": "md_1min_bars",
|
||||||
|
|
||||||
|
# ----- Instruments
|
||||||
|
"exchange_id": "ALPACA",
|
||||||
|
"instrument_id_pfx": "STOCK-",
|
||||||
|
|
||||||
"instruments": [
|
"instruments": [
|
||||||
"COIN",
|
"COIN",
|
||||||
"GBTC",
|
"GBTC",
|
||||||
@ -37,7 +79,14 @@ CONFIG: Dict = {
|
|||||||
"MSTR",
|
"MSTR",
|
||||||
"PYPL",
|
"PYPL",
|
||||||
],
|
],
|
||||||
"trading_hours": {"begin_session": "14:30:00", "end_session": "21:00:00"},
|
|
||||||
|
"trading_hours": {
|
||||||
|
"begin_session": "9:30:00",
|
||||||
|
"end_session": "16:00:00",
|
||||||
|
"timezone": "America/New_York"
|
||||||
|
},
|
||||||
|
|
||||||
|
# ----- Model Settings
|
||||||
"price_column": "close",
|
"price_column": "close",
|
||||||
"min_required_points": 30,
|
"min_required_points": 30,
|
||||||
"zero_threshold": 1e-10,
|
"zero_threshold": 1e-10,
|
||||||
@ -45,33 +94,18 @@ CONFIG: Dict = {
|
|||||||
"equilibrium_threshold_close": 1.0,
|
"equilibrium_threshold_close": 1.0,
|
||||||
"training_minutes": 120,
|
"training_minutes": 120,
|
||||||
|
|
||||||
|
# ----- Validation
|
||||||
"funding_per_pair": 2000.0,
|
"funding_per_pair": 2000.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
# ====== later ===================
|
# ==========================================================================
|
||||||
# # Try to load configuration from file, fall back to defaults if not found
|
CONFIG = EQT_CONFIG
|
||||||
# CONFIG_FILE = "config.json"
|
|
||||||
# try:
|
|
||||||
# with open(CONFIG_FILE, "r") as f:
|
|
||||||
# user_config = json.load(f)
|
|
||||||
# CONFIG.update(user_config)
|
|
||||||
# print(f"Loaded configuration from {CONFIG_FILE}")
|
|
||||||
# except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
||||||
# print(f"Using default configuration. Error loading {CONFIG_FILE}: {str(e)}")
|
|
||||||
# # Create a default config file if it doesn't exist
|
|
||||||
# try:
|
|
||||||
# with open(CONFIG_FILE, "w") as f:
|
|
||||||
# json.dump(CONFIG, f, indent=4)
|
|
||||||
# print(f"Created default configuration file: {CONFIG_FILE}")
|
|
||||||
# except Exception as e:
|
|
||||||
# print(f"Warning: Could not create default config file: {str(e)}")
|
|
||||||
# ------------------------ Settings ------------------------
|
|
||||||
|
|
||||||
TRADES = {}
|
TRADES = {}
|
||||||
TOTAL_UNREALIZED_PNL = 0.0 # Global variable to track total unrealized PnL
|
TOTAL_UNREALIZED_PNL = 0.0 # Global variable to track total unrealized PnL
|
||||||
TOTAL_REALIZED_PNL = 0.0 # Global variable to track total realized PnL
|
TOTAL_REALIZED_PNL = 0.0 # Global variable to track total realized PnL
|
||||||
OUTSTANDING_POSITIONS = [] # Global list to track outstanding positions with share quantities
|
OUTSTANDING_POSITIONS = [] # Global list to track outstanding positions with share quantities
|
||||||
class Pair:
|
|
||||||
|
class TradingPair:
|
||||||
symbol_a_: str
|
symbol_a_: str
|
||||||
symbol_b_: str
|
symbol_b_: str
|
||||||
price_column_: str
|
price_column_: str
|
||||||
@ -81,17 +115,35 @@ class Pair:
|
|||||||
self.symbol_b_ = symbol_b
|
self.symbol_b_ = symbol_b
|
||||||
self.price_column_ = price_column
|
self.price_column_ = price_column
|
||||||
|
|
||||||
|
|
||||||
def colnames(self) -> List[str]:
|
def colnames(self) -> List[str]:
|
||||||
return [f"{self.price_column_}_{self.symbol_a_}", f"{self.price_column_}_{self.symbol_b_}"]
|
return [f"{self.price_column_}_{self.symbol_a_}", f"{self.price_column_}_{self.symbol_b_}"]
|
||||||
|
|
||||||
def __repr__(self) ->str:
|
def __repr__(self) ->str:
|
||||||
return f"{self.symbol_a_} & {self.symbol_b_}"
|
return f"{self.symbol_a_} & {self.symbol_b_}"
|
||||||
|
|
||||||
|
def convert_time_to_UTC(value: str, timezone: str):
|
||||||
|
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Parse it to naive datetime object
|
||||||
|
local_dt = datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
zinfo = ZoneInfo(timezone)
|
||||||
|
result = local_dt.replace(tzinfo=zinfo)
|
||||||
|
|
||||||
|
result = result.astimezone(ZoneInfo('UTC'))
|
||||||
|
result = result.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
def load_market_data(datafile: str) -> pd.DataFrame:
|
def load_market_data(datafile: str) -> pd.DataFrame:
|
||||||
from tools.data_loader import load_sqlite_to_dataframe
|
from tools.data_loader import load_sqlite_to_dataframe
|
||||||
|
|
||||||
instrument_ids = ["\"" + "STOCK-" + instrument + "\"" for instrument in CONFIG["instruments"]]
|
instrument_ids = ["\"" + CONFIG["instrument_id_pfx"] + instrument + "\"" for instrument in CONFIG["instruments"]]
|
||||||
exchange_id = CONFIG["exchange_id"]
|
exchange_id = CONFIG["exchange_id"]
|
||||||
|
|
||||||
query = "select tstamp"
|
query = "select tstamp"
|
||||||
@ -105,7 +157,7 @@ def load_market_data(datafile: str) -> pd.DataFrame:
|
|||||||
query += ", num_trades"
|
query += ", num_trades"
|
||||||
query += ", vwap"
|
query += ", vwap"
|
||||||
|
|
||||||
query += " from md_1min_bars"
|
query += f" from {CONFIG['db_table_name']}"
|
||||||
query += f" where exchange_id ='{exchange_id}'"
|
query += f" where exchange_id ='{exchange_id}'"
|
||||||
query += f" and instrument_id in ({','.join(instrument_ids)})"
|
query += f" and instrument_id in ({','.join(instrument_ids)})"
|
||||||
|
|
||||||
@ -113,8 +165,12 @@ def load_market_data(datafile: str) -> pd.DataFrame:
|
|||||||
|
|
||||||
# Trading Hours
|
# Trading Hours
|
||||||
date_str = df["tstamp"][0][0:10]
|
date_str = df["tstamp"][0][0:10]
|
||||||
start_time = f"{date_str} {CONFIG['trading_hours']['begin_session']}"
|
trading_hours = CONFIG['trading_hours']
|
||||||
end_time = f"{date_str} {CONFIG['trading_hours']['end_session']}"
|
start_time = f"{date_str} {trading_hours['begin_session']}"
|
||||||
|
end_time = f"{date_str} {trading_hours['end_session']}"
|
||||||
|
|
||||||
|
start_time = convert_time_to_UTC(start_time, trading_hours["timezone"])
|
||||||
|
end_time = convert_time_to_UTC(end_time, trading_hours["timezone"])
|
||||||
|
|
||||||
# Perform boolean selection
|
# Perform boolean selection
|
||||||
df = df[(df["tstamp"] >= start_time) & (df["tstamp"] <= end_time)]
|
df = df[(df["tstamp"] >= start_time) & (df["tstamp"] <= end_time)]
|
||||||
@ -149,7 +205,7 @@ def transform_dataframe(df: pd.DataFrame, price_column: str):
|
|||||||
|
|
||||||
return result_df
|
return result_df
|
||||||
|
|
||||||
def get_datasets(df: pd.DataFrame, training_minutes: int, pair: Pair) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
def get_datasets(df: pd.DataFrame, training_minutes: int, pair: TradingPair) -> Tuple[pd.DataFrame, pd.DataFrame]:
|
||||||
# Training dataset
|
# Training dataset
|
||||||
colname_a, colname_b = pair.colnames()
|
colname_a, colname_b = pair.colnames()
|
||||||
df = df[["tstamp", colname_a, colname_b]]
|
df = df[["tstamp", colname_a, colname_b]]
|
||||||
@ -164,7 +220,7 @@ def get_datasets(df: pd.DataFrame, training_minutes: int, pair: Pair) -> Tuple[p
|
|||||||
|
|
||||||
return (training_df, testing_df)
|
return (training_df, testing_df)
|
||||||
|
|
||||||
def fit_VECM(training_pair_df, pair: Pair):
|
def fit_VECM(training_pair_df, pair: TradingPair):
|
||||||
vecm_model = VECM(training_pair_df[pair.colnames()].reset_index(drop=True), coint_rank=1)
|
vecm_model = VECM(training_pair_df[pair.colnames()].reset_index(drop=True), coint_rank=1)
|
||||||
vecm_fit = vecm_model.fit()
|
vecm_fit = vecm_model.fit()
|
||||||
|
|
||||||
@ -174,7 +230,7 @@ def fit_VECM(training_pair_df, pair: Pair):
|
|||||||
|
|
||||||
return vecm_fit
|
return vecm_fit
|
||||||
|
|
||||||
def create_trading_signals(vecm_fit, testing_pair_df, pair: Pair) -> pd.DataFrame:
|
def create_trading_signals(vecm_fit, testing_pair_df, pair: TradingPair) -> pd.DataFrame:
|
||||||
result_columns = [
|
result_columns = [
|
||||||
"time",
|
"time",
|
||||||
"action",
|
"action",
|
||||||
@ -401,7 +457,7 @@ def create_trading_signals(vecm_fit, testing_pair_df, pair: Pair) -> pd.DataFram
|
|||||||
columns=result_columns,
|
columns=result_columns,
|
||||||
)
|
)
|
||||||
|
|
||||||
def run_single_pair(market_data: pd.DataFrame, price_column:str, pair: Pair) -> Optional[pd.DataFrame]:
|
def run_single_pair(market_data: pd.DataFrame, price_column:str, pair: TradingPair) -> Optional[pd.DataFrame]:
|
||||||
colname_a = f"{price_column}_{pair.symbol_a_}"
|
colname_a = f"{price_column}_{pair.symbol_a_}"
|
||||||
colname_b = f"{price_column}_{pair.symbol_b_}"
|
colname_b = f"{price_column}_{pair.symbol_b_}"
|
||||||
training_pair_df, testing_pair_df = get_datasets(df=market_data, training_minutes=CONFIG["training_minutes"], pair=pair)
|
training_pair_df, testing_pair_df = get_datasets(df=market_data, training_minutes=CONFIG["training_minutes"], pair=pair)
|
||||||
@ -447,16 +503,15 @@ def run_single_pair(market_data: pd.DataFrame, price_column:str, pair: Pair) ->
|
|||||||
|
|
||||||
return pair_trades
|
return pair_trades
|
||||||
|
|
||||||
def add_trade(pair, symbol, action, price):
|
def add_trade(pair_nm, symbol, action, price):
|
||||||
# Ensure we always use clean names without STOCK- prefix
|
pair_nm = str(pair_nm)
|
||||||
pair = str(pair).replace("STOCK-", "")
|
|
||||||
symbol = symbol.replace("STOCK-", "")
|
|
||||||
|
|
||||||
if pair not in TRADES:
|
|
||||||
TRADES[pair] = {symbol: []}
|
if pair_nm not in TRADES:
|
||||||
if symbol not in TRADES[pair]:
|
TRADES[pair_nm] = {symbol: []}
|
||||||
TRADES[pair][symbol] = []
|
if symbol not in TRADES[pair_nm]:
|
||||||
TRADES[pair][symbol].append((action, price))
|
TRADES[pair_nm][symbol] = []
|
||||||
|
TRADES[pair_nm][symbol].append((action, price))
|
||||||
|
|
||||||
def collect_single_day_results(result):
|
def collect_single_day_results(result):
|
||||||
if result is None:
|
if result is None:
|
||||||
@ -469,7 +524,7 @@ def collect_single_day_results(result):
|
|||||||
action = row.action
|
action = row.action
|
||||||
symbol = row.symbol
|
symbol = row.symbol
|
||||||
price = row.price
|
price = row.price
|
||||||
add_trade(pair=row.pair, action=action, symbol=symbol, price=price)
|
add_trade(pair_nm=row.pair, action=action, symbol=symbol, price=price)
|
||||||
|
|
||||||
def print_single_day_results(result):
|
def print_single_day_results(result):
|
||||||
for pair, symbols in TRADES.items():
|
for pair, symbols in TRADES.items():
|
||||||
@ -574,10 +629,8 @@ def run_pairs(summaries_df: pd.DataFrame, price_column: str) -> None:
|
|||||||
colname_b = stock_price_columns[b_index]
|
colname_b = stock_price_columns[b_index]
|
||||||
|
|
||||||
symbol_a = colname_a[len(f"{price_column}-") :]
|
symbol_a = colname_a[len(f"{price_column}-") :]
|
||||||
symbol_b = colname_b[len(f"{price_column}-") :].replace(
|
symbol_b = colname_b[len(f"{price_column}-") :]
|
||||||
"STOCK-", ""
|
pair = TradingPair(symbol_a, symbol_b, price_column)
|
||||||
)
|
|
||||||
pair = Pair(symbol_a, symbol_b, price_column)
|
|
||||||
|
|
||||||
single_pair_trades = run_single_pair(market_data=result_df, price_column=price_column, pair=pair)
|
single_pair_trades = run_single_pair(market_data=result_df, price_column=price_column, pair=pair)
|
||||||
if len(single_pair_trades) > 0:
|
if len(single_pair_trades) > 0:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user