Fix int64 JSON serialization error in SocketIO responses
- Add utils.py with sanitize_for_json() function to convert numpy types (int64, float64, bool_, ndarray) to native Python types - Handle inf/nan values by converting to None - Update backtesting.py to use shared sanitize_for_json utility - Update app.py strategy_events emit to sanitize data before sending - Remove empty root BrighterTrading.db and add *.db to gitignore Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4e14463465
commit
3644c219d4
|
|
@ -10,6 +10,7 @@ flask_session/
|
|||
# Ignore databases
|
||||
data/
|
||||
data/*.db
|
||||
*.db
|
||||
|
||||
# Ignore configuration files
|
||||
config/
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ from email_validator import validate_email, EmailNotValidError # noqa: E402
|
|||
|
||||
# Local application imports
|
||||
from BrighterTrades import BrighterTrades # noqa: E402
|
||||
from utils import sanitize_for_json # noqa: E402
|
||||
|
||||
# Set up logging
|
||||
log_level_name = os.getenv('BRIGHTER_LOG_LEVEL', 'INFO').upper()
|
||||
|
|
@ -128,11 +129,11 @@ def strategy_execution_loop():
|
|||
# Emit events to the user's room
|
||||
user_name = brighter_trades.users.get_username(user_id=user_id)
|
||||
if user_name:
|
||||
socketio.emit('strategy_events', {
|
||||
socketio.emit('strategy_events', sanitize_for_json({
|
||||
'strategy_id': strategy_id,
|
||||
'mode': mode,
|
||||
'events': events
|
||||
}, room=user_name)
|
||||
}), room=user_name)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not get price for {symbol}: {e}")
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from mapped_strategy import MappedStrategy
|
|||
import numpy as np
|
||||
import pandas as pd
|
||||
import signal
|
||||
from utils import sanitize_for_json
|
||||
|
||||
# Configure logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -821,26 +822,15 @@ class Backtester:
|
|||
}
|
||||
|
||||
def sanitize_results(self, results):
|
||||
import math
|
||||
for key, value in results.items():
|
||||
if isinstance(value, float) and (math.isinf(value) or math.isnan(value)):
|
||||
results[key] = None # Replace `inf` or `nan` with `None`
|
||||
elif isinstance(value, list):
|
||||
results[key] = self.sanitize_results_in_list(value)
|
||||
elif isinstance(value, dict):
|
||||
results[key] = self.sanitize_results(value)
|
||||
return results
|
||||
"""
|
||||
Recursively sanitize a dictionary for JSON serialization.
|
||||
Converts numpy types to native Python types and handles inf/nan.
|
||||
"""
|
||||
return sanitize_for_json(results)
|
||||
|
||||
def sanitize_results_in_list(self, results_list):
|
||||
sanitized_list = []
|
||||
for item in results_list:
|
||||
if isinstance(item, dict):
|
||||
sanitized_list.append(self.sanitize_results(item))
|
||||
elif isinstance(item, float) and (math.isinf(item) or math.isnan(item)):
|
||||
sanitized_list.append(None)
|
||||
else:
|
||||
sanitized_list.append(item)
|
||||
return sanitized_list
|
||||
"""Sanitize a list for JSON serialization."""
|
||||
return sanitize_for_json(results_list)
|
||||
|
||||
def update_strategy_stats(self, tbl_key: str, results: dict):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
"""
|
||||
Utility functions for BrighterTrading.
|
||||
"""
|
||||
import math
|
||||
import numpy as np
|
||||
|
||||
|
||||
def sanitize_for_json(value):
|
||||
"""
|
||||
Convert a value to a JSON-serializable type.
|
||||
Handles numpy types, inf, nan, and nested structures.
|
||||
|
||||
:param value: Any value that needs to be JSON serialized
|
||||
:return: JSON-serializable value
|
||||
"""
|
||||
# Handle None
|
||||
if value is None:
|
||||
return None
|
||||
# Handle numpy integer types
|
||||
if isinstance(value, np.integer):
|
||||
return int(value)
|
||||
# Handle numpy floating types
|
||||
elif isinstance(value, np.floating):
|
||||
float_val = float(value)
|
||||
if math.isinf(float_val) or math.isnan(float_val):
|
||||
return None
|
||||
return float_val
|
||||
# Handle numpy boolean
|
||||
elif isinstance(value, np.bool_):
|
||||
return bool(value)
|
||||
# Handle numpy arrays
|
||||
elif isinstance(value, np.ndarray):
|
||||
return [sanitize_for_json(v) for v in value.tolist()]
|
||||
# Handle regular floats with inf/nan
|
||||
elif isinstance(value, float):
|
||||
if math.isinf(value) or math.isnan(value):
|
||||
return None
|
||||
return value
|
||||
# Handle nested dicts
|
||||
elif isinstance(value, dict):
|
||||
return {k: sanitize_for_json(v) for k, v in value.items()}
|
||||
# Handle lists
|
||||
elif isinstance(value, list):
|
||||
return [sanitize_for_json(v) for v in value]
|
||||
# Handle tuples
|
||||
elif isinstance(value, tuple):
|
||||
return tuple(sanitize_for_json(v) for v in value)
|
||||
# Return other types as-is (str, int, bool, etc.)
|
||||
return value
|
||||
|
||||
|
||||
def sanitize_dict_for_json(data: dict) -> dict:
|
||||
"""
|
||||
Sanitize a dictionary for JSON serialization.
|
||||
Convenience wrapper around sanitize_for_json for dictionaries.
|
||||
|
||||
:param data: Dictionary to sanitize
|
||||
:return: JSON-serializable dictionary
|
||||
"""
|
||||
return sanitize_for_json(data)
|
||||
Loading…
Reference in New Issue