timezone converting added
This commit is contained in:
parent
eda31d01fd
commit
0d0dde897d
@ -16,8 +16,44 @@ UNSET_INT: int = sys.maxsize
|
||||
|
||||
# ------------------------ Configuration ------------------------
|
||||
# Default configuration
|
||||
CONFIG: Dict = {
|
||||
"exchange_id": "ALPACA",
|
||||
CRYPTO_CONFIG: Dict = {
|
||||
# --- 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",
|
||||
"datafiles": [
|
||||
"20250508.alpaca_sim_md.db",
|
||||
@ -30,6 +66,12 @@ CONFIG: Dict = {
|
||||
# "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",
|
||||
@ -37,7 +79,14 @@ CONFIG: Dict = {
|
||||
"MSTR",
|
||||
"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",
|
||||
"min_required_points": 30,
|
||||
"zero_threshold": 1e-10,
|
||||
@ -45,33 +94,18 @@ CONFIG: Dict = {
|
||||
"equilibrium_threshold_close": 1.0,
|
||||
"training_minutes": 120,
|
||||
|
||||
# ----- Validation
|
||||
"funding_per_pair": 2000.0,
|
||||
}
|
||||
|
||||
# ====== later ===================
|
||||
# # Try to load configuration from file, fall back to defaults if not found
|
||||
# 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 ------------------------
|
||||
|
||||
# ==========================================================================
|
||||
CONFIG = EQT_CONFIG
|
||||
TRADES = {}
|
||||
TOTAL_UNREALIZED_PNL = 0.0 # Global variable to track total unrealized PnL
|
||||
TOTAL_REALIZED_PNL = 0.0 # Global variable to track total realized PnL
|
||||
OUTSTANDING_POSITIONS = [] # Global list to track outstanding positions with share quantities
|
||||
class Pair:
|
||||
|
||||
class TradingPair:
|
||||
symbol_a_: str
|
||||
symbol_b_: str
|
||||
price_column_: str
|
||||
@ -81,17 +115,35 @@ class Pair:
|
||||
self.symbol_b_ = symbol_b
|
||||
self.price_column_ = price_column
|
||||
|
||||
|
||||
def colnames(self) -> List[str]:
|
||||
return [f"{self.price_column_}_{self.symbol_a_}", f"{self.price_column_}_{self.symbol_b_}"]
|
||||
|
||||
def __repr__(self) ->str:
|
||||
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:
|
||||
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"]
|
||||
|
||||
query = "select tstamp"
|
||||
@ -105,7 +157,7 @@ def load_market_data(datafile: str) -> pd.DataFrame:
|
||||
query += ", num_trades"
|
||||
query += ", vwap"
|
||||
|
||||
query += " from md_1min_bars"
|
||||
query += f" from {CONFIG['db_table_name']}"
|
||||
query += f" where exchange_id ='{exchange_id}'"
|
||||
query += f" and instrument_id in ({','.join(instrument_ids)})"
|
||||
|
||||
@ -113,8 +165,12 @@ def load_market_data(datafile: str) -> pd.DataFrame:
|
||||
|
||||
# Trading Hours
|
||||
date_str = df["tstamp"][0][0:10]
|
||||
start_time = f"{date_str} {CONFIG['trading_hours']['begin_session']}"
|
||||
end_time = f"{date_str} {CONFIG['trading_hours']['end_session']}"
|
||||
trading_hours = CONFIG['trading_hours']
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
colname_a, colname_b = pair.colnames()
|
||||
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)
|
||||
|
||||
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_fit = vecm_model.fit()
|
||||
|
||||
@ -174,7 +230,7 @@ def fit_VECM(training_pair_df, pair: Pair):
|
||||
|
||||
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 = [
|
||||
"time",
|
||||
"action",
|
||||
@ -401,7 +457,7 @@ def create_trading_signals(vecm_fit, testing_pair_df, pair: Pair) -> pd.DataFram
|
||||
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_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)
|
||||
@ -447,16 +503,15 @@ def run_single_pair(market_data: pd.DataFrame, price_column:str, pair: Pair) ->
|
||||
|
||||
return pair_trades
|
||||
|
||||
def add_trade(pair, symbol, action, price):
|
||||
# Ensure we always use clean names without STOCK- prefix
|
||||
pair = str(pair).replace("STOCK-", "")
|
||||
symbol = symbol.replace("STOCK-", "")
|
||||
def add_trade(pair_nm, symbol, action, price):
|
||||
pair_nm = str(pair_nm)
|
||||
|
||||
if pair not in TRADES:
|
||||
TRADES[pair] = {symbol: []}
|
||||
if symbol not in TRADES[pair]:
|
||||
TRADES[pair][symbol] = []
|
||||
TRADES[pair][symbol].append((action, price))
|
||||
|
||||
if pair_nm not in TRADES:
|
||||
TRADES[pair_nm] = {symbol: []}
|
||||
if symbol not in TRADES[pair_nm]:
|
||||
TRADES[pair_nm][symbol] = []
|
||||
TRADES[pair_nm][symbol].append((action, price))
|
||||
|
||||
def collect_single_day_results(result):
|
||||
if result is None:
|
||||
@ -469,7 +524,7 @@ def collect_single_day_results(result):
|
||||
action = row.action
|
||||
symbol = row.symbol
|
||||
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):
|
||||
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]
|
||||
|
||||
symbol_a = colname_a[len(f"{price_column}-") :]
|
||||
symbol_b = colname_b[len(f"{price_column}-") :].replace(
|
||||
"STOCK-", ""
|
||||
)
|
||||
pair = Pair(symbol_a, symbol_b, price_column)
|
||||
symbol_b = colname_b[len(f"{price_column}-") :]
|
||||
pair = TradingPair(symbol_a, symbol_b, price_column)
|
||||
|
||||
single_pair_trades = run_single_pair(market_data=result_df, price_column=price_column, pair=pair)
|
||||
if len(single_pair_trades) > 0:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user