Settings Manager
settings
The settings module provides a hierarchical configuration management system for the Quantstrip trading platform. It stores all application settings in a JSON file with support for typed values, encryption for sensitive data, and a path-based navigation system.
Key Features
- Hierarchical folder structure for organizing settings
- Type-safe values (text, float, bool, list, dict, secret)
- Automatic encryption/decryption for sensitive data (secrets)
- Path-based navigation (e.g.,
/config/Settings/Database/Host) - Locked folders to prevent accidental deletion
- JSON-based storage for easy inspection and backup
Configuration Concept
The settings system organizes configuration data in a tree structure similar to a file system:
config/
├── Settings/
│ ├── Database/
│ │ ├── Host: "localhost"
│ │ ├── Port: 5432
│ │ └── Password: (encrypted)
│ ├── Broker/
│ │ ├── IBKR/
│ │ │ ├── Host: "127.0.0.1"
│ │ │ ├── Port: 7497
│ │ │ └── Client_ID: 1
│ │ └── Account: "U1234567"
│ └── Notification/
│ └── Email Accounts/
│ └── Gmail Trading/
│ ├── SMTP_Server: "smtp.gmail.com"
│ ├── SMTP_Port: 587
│ └── Password: (encrypted)
Setting Types
Each setting has a _type that determines how its value is stored and parsed:
| Type | Description | Example Use |
|---|---|---|
text |
String values (default) | Hostnames, usernames, names |
float |
Floating point numbers | Prices, percentages, ratios |
bool |
Boolean true/false | Enable/disable flags |
list |
Array of values | Multiple accounts, symbols |
dict |
Key-value pairs | Complex configuration objects |
secret |
Encrypted strings | Passwords, API keys, tokens |
Internal Storage Format
Settings are stored internally as JSON objects with _value and _type fields:
{
"config": {
"Settings": {
"Database": {
"Host": {
"_value": "localhost",
"_type": "text"
},
"Port": {
"_value": 5432,
"_type": "float"
},
"Password": {
"_value": "ZW5jcnlwdGVkX3N0cmluZw==",
"_type": "secret"
}
}
}
}
}
Automatic Type Handling
When you use get_by_path(), the settings manager automatically:
- Decrypts
secrettype values - Parses
floatvalues to numbers - Converts
boolvalues to Python booleans - Returns
listanddictas native Python types
You don't need to handle encryption or type conversion manually.
Initialization
Import settings from quantstrip
from quantstrip import settings as config
The settings manager automatically creates a default configuration file if it doesn't exist at /Data/config.json.
Core Methods
Reading Settings
get_by_path(path)
Get a setting value by path. Automatically decrypts secrets and parses values according to their type.
Parameters:
| Parameter | Type | Description |
|---|---|---|
path |
str |
Path to setting (e.g., "/config/Settings/Database/Host") |
Returns: Parsed value according to type, or None if not found
Path Format
- Paths use forward slashes as separators:
/config/Settings/Database/Host - The
/configprefix is optional and will be added automatically if omitted - Paths are case-sensitive and must match the actual folder/setting names
Example:
# Get text value
host = config.get_by_path("/config/Settings/Database/Host")
print(host) # "localhost"
# Get numeric value
port = config.get_by_path("/config/Settings/Database/Port")
print(port) # 5432 (as float)
# Get boolean value
enabled = config.get_by_path("/config/Settings/Feature/Enabled")
print(enabled) # True or False
# Get encrypted secret (automatically decrypted)
password = config.get_by_path("/config/Settings/Database/Password")
print(password) # "my_secret_password" (decrypted)
# Get list value
accounts = config.get_by_path("/config/Settings/Broker/Accounts")
print(accounts) # ["U1234567", "U7654321"]
# Get dict value
smtp_config = config.get_by_path("/config/Settings/Email/SMTP")
print(smtp_config) # {"server": "smtp.gmail.com", "port": 587}
# Path with 'config' prefix omitted (automatically added)
host = config.get_by_path("/Settings/Database/Host") # Same as above
Writing Settings
set_by_path(path, value, value_type="text")
Set a setting value by path. Automatically encrypts secrets and stores values with proper typing.
Parameters:
| Parameter | Type | Description |
|---|---|---|
path |
str |
Path to setting (e.g., "/config/Settings/Database/Host") |
value |
Any |
The value to store |
value_type |
str |
Type: "text", "float", "bool", "list", "dict", "secret" (default: "text") |
Returns: None (saves to config file)
Type Specification
Always specify the correct value_type when setting values. The type determines how the value is stored and parsed when retrieved:
- Use
"secret"for sensitive data (passwords, API keys) - Use
"float"for numeric values - Use
"bool"for true/false flags - Use
"list"for arrays - Use
"dict"for objects - Use
"text"for strings (default)
Example:
# Set text value
config.set_by_path(
"/config/Settings/Database/Host",
"localhost",
value_type="text"
)
# Set numeric value
config.set_by_path(
"/config/Settings/Database/Port",
5432,
value_type="float"
)
# Set boolean value
config.set_by_path(
"/config/Settings/Feature/Enabled",
True,
value_type="bool"
)
# Set encrypted secret
config.set_by_path(
"/config/Settings/Database/Password",
"my_secret_password",
value_type="secret" # Will be encrypted automatically
)
# Set list value
config.set_by_path(
"/config/Settings/Broker/Accounts",
["U1234567", "U7654321"],
value_type="list"
)
# Set dict value
config.set_by_path(
"/config/Settings/Email/SMTP",
{"server": "smtp.gmail.com", "port": 587},
value_type="dict"
)
# Value type defaults to "text" if not specified
config.set_by_path(
"/config/Settings/Broker/Name",
"Interactive Brokers"
)
Common Usage Patterns
Broker Configuration
# Set up IBKR connection settings
config.set_by_path("/Settings/Broker/IBKR/Host", "127.0.0.1", "text")
config.set_by_path("/Settings/Broker/IBKR/Port", 7497, "float")
config.set_by_path("/Settings/Broker/IBKR/Client_ID", 1, "float")
config.set_by_path("/Settings/Broker/IBKR/Account", "U1234567", "text")
# Read broker settings
ibkr_host = config.get_by_path("/Settings/Broker/IBKR/Host")
ibkr_port = int(config.get_by_path("/Settings/Broker/IBKR/Port"))
client_id = int(config.get_by_path("/Settings/Broker/IBKR/Client_ID"))
account = config.get_by_path("/Settings/Broker/IBKR/Account")
# Connect to broker
broker.connect(ibkr_host, ibkr_port, client_id)
Email Configuration
# Set up email account with encrypted password
config.set_by_path(
"/Settings/Notification/Email/SMTP_Server",
"smtp.gmail.com",
"text"
)
config.set_by_path(
"/Settings/Notification/Email/SMTP_Port",
587,
"float"
)
config.set_by_path(
"/Settings/Notification/Email/Username",
"trading@gmail.com",
"text"
)
config.set_by_path(
"/Settings/Notification/Email/Password",
"my_app_password",
"secret" # Encrypted automatically
)
config.set_by_path(
"/Settings/Notification/Email/Use_TLS",
True,
"bool"
)
# Read email settings (password is automatically decrypted)
smtp_server = config.get_by_path("/Settings/Notification/Email/SMTP_Server")
smtp_port = int(config.get_by_path("/Settings/Notification/Email/SMTP_Port"))
username = config.get_by_path("/Settings/Notification/Email/Username")
password = config.get_by_path("/Settings/Notification/Email/Password") # Decrypted
use_tls = config.get_by_path("/Settings/Notification/Email/Use_TLS")
# Use in email client
import smtplib
server = smtplib.SMTP(smtp_server, smtp_port)
if use_tls:
server.starttls()
server.login(username, password)
Strategy Parameters
# Store strategy configuration
config.set_by_path(
"/Settings/Strategies/Momentum/Lookback_Period",
20,
"float"
)
config.set_by_path(
"/Settings/Strategies/Momentum/Entry_Threshold",
0.02,
"float"
)
config.set_by_path(
"/Settings/Strategies/Momentum/Symbols",
["AAPL", "MSFT", "GOOGL", "AMZN"],
"list"
)
config.set_by_path(
"/Settings/Strategies/Momentum/Enabled",
True,
"bool"
)
config.set_by_path(
"/Settings/Strategies/Momentum/Risk_Params",
{
"max_position_size": 1000,
"stop_loss_pct": 0.02,
"take_profit_pct": 0.05
},
"dict"
)
# Read strategy parameters
lookback = int(config.get_by_path("/Settings/Strategies/Momentum/Lookback_Period"))
threshold = config.get_by_path("/Settings/Strategies/Momentum/Entry_Threshold")
symbols = config.get_by_path("/Settings/Strategies/Momentum/Symbols")
enabled = config.get_by_path("/Settings/Strategies/Momentum/Enabled")
risk_params = config.get_by_path("/Settings/Strategies/Momentum/Risk_Params")
# Use in strategy
if enabled:
for symbol in symbols:
if check_momentum(symbol, lookback) > threshold:
position_size = min(1000, risk_params["max_position_size"])
place_order(symbol, position_size)
Database Configuration
# Store database connection settings
config.set_by_path("/Settings/Database/Host", "localhost", "text")
config.set_by_path("/Settings/Database/Port", 5432, "float")
config.set_by_path("/Settings/Database/Database", "trading_db", "text")
config.set_by_path("/Settings/Database/Username", "trader", "text")
config.set_by_path("/Settings/Database/Password", "secure_password", "secret")
config.set_by_path("/Settings/Database/Use_SSL", True, "bool")
# Read and use database settings
db_config = {
"host": config.get_by_path("/Settings/Database/Host"),
"port": int(config.get_by_path("/Settings/Database/Port")),
"database": config.get_by_path("/Settings/Database/Database"),
"user": config.get_by_path("/Settings/Database/Username"),
"password": config.get_by_path("/Settings/Database/Password"), # Decrypted
"sslmode": "require" if config.get_by_path("/Settings/Database/Use_SSL") else "disable"
}
# Connect to database
import psycopg2
conn = psycopg2.connect(**db_config)
Feature Flags
# Store feature flags
config.set_by_path("/Settings/Features/Paper_Trading", True, "bool")
config.set_by_path("/Settings/Features/Email_Notifications", True, "bool")
config.set_by_path("/Settings/Features/Real_Time_Data", False, "bool")
config.set_by_path("/Settings/Features/Advanced_Orders", True, "bool")
# Use feature flags in application
if config.get_by_path("/Settings/Features/Paper_Trading"):
print("Running in paper trading mode")
broker = PaperBroker()
else:
print("Running in live trading mode")
broker = LiveBroker()
if config.get_by_path("/Settings/Features/Email_Notifications"):
send_notification("Trading session started")
if config.get_by_path("/Settings/Features/Advanced_Orders"):
enable_bracket_orders()
enable_trailing_stops()
Multiple Trading Accounts
# Store multiple account configurations
accounts = {
"primary": {
"account_id": "U1234567",
"broker": "IBKR",
"enabled": True
},
"secondary": {
"account_id": "U7654321",
"broker": "IBKR",
"enabled": False
}
}
config.set_by_path("/Settings/Accounts", accounts, "dict")
# Read and use accounts
all_accounts = config.get_by_path("/Settings/Accounts")
for name, details in all_accounts.items():
if details["enabled"]:
print(f"Trading with {name}: {details['account_id']}")
broker.connect(account=details["account_id"])
Best Practices
1. Always Use the Correct Type
# ✓ GOOD - Correct types specified
config.set_by_path("/Settings/Port", 7497, "float")
config.set_by_path("/Settings/Enabled", True, "bool")
config.set_by_path("/Settings/API_Key", "secret_key", "secret")
# ✗ BAD - Wrong or missing types
config.set_by_path("/Settings/Port", 7497) # Stored as text "7497"
config.set_by_path("/Settings/Enabled", "true") # Stored as text, not bool
config.set_by_path("/Settings/API_Key", "secret_key") # Not encrypted!
2. Validate Retrieved Values
# Get value with validation
port = config.get_by_path("/Settings/Broker/Port")
if port is None:
port = 7497 # Default value
config.set_by_path("/Settings/Broker/Port", port, "float")
# Convert to appropriate Python type if needed
port = int(port) # Convert float to int for socket connection
3. Use Descriptive Path Names
# ✓ GOOD - Clear, descriptive paths
config.set_by_path("/Settings/Broker/IBKR/Connection/Host", "127.0.0.1", "text")
config.set_by_path("/Settings/Strategies/Momentum/Entry_Threshold", 0.02, "float")
config.set_by_path("/Settings/Notification/Email/Daily_Report/Enabled", True, "bool")
# ✗ BAD - Ambiguous paths
config.set_by_path("/Settings/H", "127.0.0.1", "text")
config.set_by_path("/Settings/T", 0.02, "float")
config.set_by_path("/Settings/E", True, "bool")
4. Group Related Settings
# ✓ GOOD - Organized by category
config.set_by_path("/Settings/Broker/IBKR/Host", "127.0.0.1", "text")
config.set_by_path("/Settings/Broker/IBKR/Port", 7497, "float")
config.set_by_path("/Settings/Broker/IBKR/Client_ID", 1, "float")
# ✗ BAD - Scattered settings
config.set_by_path("/Settings/IBKR_Host", "127.0.0.1", "text")
config.set_by_path("/Settings/Port", 7497, "float")
config.set_by_path("/Settings/ID", 1, "float")
5. Never Store Secrets as Plain Text
# ✓ GOOD - Secret type for sensitive data
config.set_by_path(
"/Settings/API/Key",
"sk_live_abc123xyz",
"secret" # Encrypted
)
config.set_by_path(
"/Settings/Database/Password",
"my_password",
"secret" # Encrypted
)
# ✗ BAD - Plain text secrets
config.set_by_path(
"/Settings/API/Key",
"sk_live_abc123xyz",
"text" # NOT encrypted!
)
Security Considerations
Encryption Strength
The built-in encryption uses simple base64 encoding with rotation. This provides basic obfuscation but is not cryptographically secure. For production systems with sensitive data:
- Consider implementing stronger encryption (e.g., using
cryptographylibrary) - Store highly sensitive credentials in environment variables or a secrets manager
- Never commit the
config.jsonfile to version control - Use proper file permissions to restrict access to the config file
Recommended Production Setup
import os
# For highly sensitive data, use environment variables
api_key = os.environ.get("TRADING_API_KEY")
# Store in config only if not available in environment
if api_key:
# Use environment variable
connect_to_api(api_key)
else:
# Fall back to encrypted config
api_key = config.get_by_path("/Settings/API/Key")
connect_to_api(api_key)
Configuration File Location
The configuration file is stored at:
/Data/config.json
This file is automatically created with default settings on first use. You can manually edit this file, but be careful to maintain the proper JSON structure with _value and _type fields for each setting.
Example Manual Edit
{
"config": {
"Settings": {
"Broker": {
"IBKR": {
"Host": {
"_value": "127.0.0.1",
"_type": "text"
},
"Port": {
"_value": 7497,
"_type": "float"
}
}
}
}
}
}
Backup Configuration
Regularly backup your config.json file, especially before making major changes. The file contains all your application settings and encrypted secrets.