Files
foxhunt/scripts/plan_databento_download.sh
jgrusewski e8a68ee39f Download 360 DBN files (36.3 MB) using Rust databento client
- Created data/examples/download_ml_training_data.rs using reqwest + Databento HTTP API
- Downloaded 90 days × 4 symbols (ES.FUT, NQ.FUT, ZN.FUT, 6E.FUT)
- Files saved to test_data/real/databento/ml_training/
- Total: 360 files, 15 MB compressed DBN format
- Used existing Rust pattern from download_nq_fut.rs
- API key loaded from .env file
- 100% success rate (360/360 files)
- Ready for ML training benchmarks

Next: Create simplified training benchmark for RTX 3050 Ti GPU measurements
2025-10-13 13:30:02 +02:00

412 lines
13 KiB
Bash
Executable File

#!/bin/bash
#
# Databento Download Planning Tool
#
# Purpose: Estimate costs, check credit balance, and generate download plan
# before actually downloading data from Databento.
#
# Usage:
# ./scripts/plan_databento_download.sh \
# --symbols "ES.FUT,NQ.FUT" \
# --days 5 \
# --schema ohlcv-1m \
# [--start-date 2024-01-02]
#
# Features:
# - Cost estimation based on historical data
# - Credit balance check (80%, 90% alerts)
# - Download command generation
# - Budget safety checks
#
set -euo pipefail
# ============================================================================
# Configuration
# ============================================================================
COST_TRACKING_FILE="${COST_TRACKING_FILE:-./COST_TRACKING.md}"
TOTAL_CREDITS="${TOTAL_CREDITS:-125.00}"
WARN_THRESHOLD_PCT="${WARN_THRESHOLD_PCT:-80}"
CRITICAL_THRESHOLD_PCT="${CRITICAL_THRESHOLD_PCT:-90}"
# Schema cost estimates (per day, per symbol)
declare -A SCHEMA_COSTS=(
["ohlcv-1m"]="0.00002"
["ohlcv-1s"]="0.0004"
["tbbo"]="0.0001"
["trades"]="0.0012"
["mbp-1"]="0.05"
["mbp-10"]="1.0"
["mbo"]="3.0"
)
# Schema file size estimates (per day, per symbol, in KB)
declare -A SCHEMA_SIZES=(
["ohlcv-1m"]="90"
["ohlcv-1s"]="1400"
["tbbo"]="50"
["trades"]="240"
["mbp-1"]="4800"
["mbp-10"]="48000"
["mbo"]="100000"
)
# ============================================================================
# Color Codes
# ============================================================================
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# ============================================================================
# Functions
# ============================================================================
usage() {
cat << EOF
Usage: $0 [OPTIONS]
Databento Download Planning Tool - Estimate costs before downloading
OPTIONS:
--symbols SYMBOLS Comma-separated list of symbols (e.g., "ES.FUT,NQ.FUT")
--days DAYS Number of days to download
--schema SCHEMA Schema type: ohlcv-1m, ohlcv-1s, tbbo, trades, mbp-1, mbp-10, mbo
--start-date DATE (Optional) Start date in YYYY-MM-DD format
--parent (Optional) Use parent symbol type (WARNING: increases cost 10-60x)
--help Show this help message
EXAMPLES:
# Single symbol, 5 days, OHLCV-1m
$0 --symbols "ES.FUT" --days 5 --schema ohlcv-1m
# Multiple symbols, 10 days, trades
$0 --symbols "ES.FUT,NQ.FUT,RTY.FUT" --days 10 --schema trades
# With specific start date
$0 --symbols "ES.FUT" --days 7 --schema ohlcv-1m --start-date 2024-01-02
SUPPORTED SCHEMAS:
ohlcv-1m 1-minute OHLCV bars (CHEAPEST, ~\$0.00002/day)
ohlcv-1s 1-second OHLCV bars (~\$0.0004/day)
tbbo Top of book quotes (~\$0.0001/day)
trades All trades (~\$0.0012/day)
mbp-1 Level 2, 1 level (~\$0.05/day)
mbp-10 Level 2, 10 levels (~\$1.00/day)
mbo Level 3, full depth (MOST EXPENSIVE, ~\$3.00/day)
EOF
exit 1
}
log_info() {
echo -e "${BLUE}[INFO]${NC} $*"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $*"
}
log_warn() {
echo -e "${YELLOW}[WARNING]${NC} $*"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*"
}
# Calculate credits used from COST_TRACKING.md
calculate_credits_used() {
if [ ! -f "$COST_TRACKING_FILE" ]; then
log_warn "Cost tracking file not found: $COST_TRACKING_FILE"
echo "0.00"
return
fi
# Extract "Estimated Cost: $X.XX - $Y.YY" lines and sum the high estimates
local total
total=$(grep -oP 'Estimated Cost: \$[\d.]+ - \$\K[\d.]+' "$COST_TRACKING_FILE" 2>/dev/null | \
awk '{sum+=$1} END {printf "%.4f", sum}')
# If no matches, return 0
if [ -z "$total" ]; then
echo "0.00"
else
echo "$total"
fi
}
# Check if credits are available for this download
check_credit_budget() {
local estimated_cost=$1
local credits_used
local credits_remaining
local usage_pct
credits_used=$(calculate_credits_used)
credits_remaining=$(echo "$TOTAL_CREDITS - $credits_used" | bc -l)
usage_pct=$(echo "scale=2; ($credits_used / $TOTAL_CREDITS) * 100" | bc -l)
echo ""
echo "======================================================================"
echo " CREDIT BUDGET STATUS"
echo "======================================================================"
printf "%-30s: \$%.4f\n" "Total Credits" "$TOTAL_CREDITS"
printf "%-30s: \$%.4f (%.1f%%)\n" "Credits Used" "$credits_used" "$usage_pct"
printf "%-30s: \$%.4f (%.1f%%)\n" "Credits Remaining" "$credits_remaining" "$(echo "100 - $usage_pct" | bc -l)"
printf "%-30s: \$%.4f\n" "Estimated Cost (This Download)" "$estimated_cost"
echo "======================================================================"
# Check alert thresholds
if (( $(echo "$usage_pct >= $CRITICAL_THRESHOLD_PCT" | bc -l) )); then
log_error "🚨 RED ALERT: Credit usage at ${usage_pct}% (>${CRITICAL_THRESHOLD_PCT}%)"
log_error "Emergency halt recommended. Executive approval required."
return 2
elif (( $(echo "$usage_pct >= $WARN_THRESHOLD_PCT" | bc -l) )); then
log_warn "🟠 ORANGE ALERT: Credit usage at ${usage_pct}% (>${WARN_THRESHOLD_PCT}%)"
log_warn "Review download necessity before proceeding."
return 1
else
log_success "✅ GREEN: Credit usage at ${usage_pct}% (budget healthy)"
return 0
fi
}
# Estimate cost for download
estimate_cost() {
local symbols=$1
local days=$2
local schema=$3
local use_parent=$4
# Count symbols
IFS=',' read -ra symbol_array <<< "$symbols"
local num_symbols=${#symbol_array[@]}
# Get base cost per day per symbol
local base_cost_per_day=${SCHEMA_COSTS[$schema]}
# Apply parent symbol multiplier if enabled
local parent_multiplier="1"
if [ "$use_parent" = true ]; then
log_warn "Parent symbol type selected: Cost multiplier 15x applied" >&2
parent_multiplier="15"
fi
# Calculate total cost
local total_cost
total_cost=$(echo "scale=4; $num_symbols * $days * $base_cost_per_day * $parent_multiplier" | bc -l)
# Estimate file size (in MB)
local base_size_kb=${SCHEMA_SIZES[$schema]}
local total_size_kb
total_size_kb=$(echo "scale=2; $num_symbols * $days * $base_size_kb * $parent_multiplier" | bc -l)
local total_size_mb
total_size_mb=$(echo "scale=2; $total_size_kb / 1024" | bc -l)
echo "$total_cost $total_size_mb"
}
# Generate download commands
generate_download_commands() {
local symbols=$1
local days=$2
local schema=$3
local start_date=$4
local use_parent=$5
# Parse symbols
IFS=',' read -ra symbol_array <<< "$symbols"
# Determine symbol type
local stype_in="continuous"
if [ "$use_parent" = true ]; then
stype_in="parent"
fi
echo ""
echo "======================================================================"
echo " DOWNLOAD COMMANDS"
echo "======================================================================"
echo ""
for symbol in "${symbol_array[@]}"; do
# Trim whitespace
symbol=$(echo "$symbol" | xargs)
for ((day=0; day<days; day++)); do
# Calculate dates
if [ -n "$start_date" ]; then
local current_date
current_date=$(date -d "$start_date + $day days" +%Y-%m-%d)
else
local current_date
current_date=$(date -d "2024-01-02 + $day days" +%Y-%m-%d)
fi
local next_date
next_date=$(date -d "$current_date + 1 day" +%Y-%m-%d)
# Generate filename
local output_file="test_data/real/databento/${symbol}_${schema}_${current_date}.dbn"
# Generate curl command
cat << EOF
# Download: $symbol, $current_date ($schema)
curl -u "\${DATABENTO_API_KEY}:" \\
"https://hist.databento.com/v0/timeseries.get_range?\\
dataset=GLBX.MDP3&\\
symbols=${symbol}&\\
schema=${schema}&\\
start=${current_date}T00:00:00Z&\\
end=${next_date}T00:00:00Z&\\
encoding=dbn&\\
stype_in=${stype_in}" \\
--output "$output_file"
# Verify download
ls -lh "$output_file"
# Update COST_TRACKING.md
echo "## Download $(date +%Y-%m-%d): $symbol ($schema)" >> COST_TRACKING.md
echo "- Symbol: $symbol" >> COST_TRACKING.md
echo "- Schema: $schema" >> COST_TRACKING.md
echo "- Date: $current_date" >> COST_TRACKING.md
echo "- File: $output_file" >> COST_TRACKING.md
echo "" >> COST_TRACKING.md
EOF
done
done
echo "======================================================================"
}
# ============================================================================
# Main
# ============================================================================
main() {
local symbols=""
local days=""
local schema=""
local start_date=""
local use_parent=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--symbols)
symbols="$2"
shift 2
;;
--days)
days="$2"
shift 2
;;
--schema)
schema="$2"
shift 2
;;
--start-date)
start_date="$2"
shift 2
;;
--parent)
use_parent=true
shift
;;
--help)
usage
;;
*)
log_error "Unknown option: $1"
usage
;;
esac
done
# Validate required arguments
if [ -z "$symbols" ] || [ -z "$days" ] || [ -z "$schema" ]; then
log_error "Missing required arguments"
usage
fi
# Validate schema
if [ -z "${SCHEMA_COSTS[$schema]:-}" ]; then
log_error "Invalid schema: $schema"
log_error "Supported schemas: ${!SCHEMA_COSTS[*]}"
exit 1
fi
# Display plan header
echo ""
echo "======================================================================"
echo " DATABENTO DOWNLOAD PLAN"
echo "======================================================================"
echo "Symbols: $symbols"
echo "Days: $days"
echo "Schema: $schema"
echo "Start Date: ${start_date:-2024-01-02 (default)}"
echo "Symbol Type: $([ "$use_parent" = true ] && echo "parent (⚠️ 15x cost!)" || echo "continuous")"
echo "======================================================================"
# Estimate cost
log_info "Estimating cost..."
read -r estimated_cost estimated_size_mb <<< "$(estimate_cost "$symbols" "$days" "$schema" "$use_parent")"
echo ""
echo "======================================================================"
echo " COST ESTIMATE"
echo "======================================================================"
printf "%-30s: \$%.4f\n" "Estimated Cost (High)" "$estimated_cost"
printf "%-30s: %.2f MB\n" "Estimated File Size" "$estimated_size_mb"
echo "======================================================================"
# Check budget
if ! check_credit_budget "$estimated_cost"; then
local exit_code=$?
if [ $exit_code -eq 2 ]; then
log_error "Download REJECTED due to credit exhaustion risk"
exit 1
else
log_warn "Download requires review before proceeding"
fi
fi
# Generate download commands
generate_download_commands "$symbols" "$days" "$schema" "$start_date" "$use_parent"
# Final recommendation
echo ""
echo "======================================================================"
echo " RECOMMENDATION"
echo "======================================================================"
if (( $(echo "$estimated_cost < 0.01" | bc -l) )); then
log_success "✅ APPROVE: Cost <\$0.01, proceed immediately"
elif (( $(echo "$estimated_cost < 0.10" | bc -l) )); then
log_info "📋 REVIEW: Cost \$0.01-\$0.10, check budget and prioritize"
elif (( $(echo "$estimated_cost < 1.00" | bc -l) )); then
log_warn "🟡 REQUIRE APPROVAL: Cost \$0.10-\$1.00, justify and review"
else
log_error "🚨 EXECUTIVE APPROVAL: Cost >\$1.00, high-cost download"
fi
echo ""
echo "Next Steps:"
echo "1. Review cost estimate and budget status"
echo "2. If approved, copy and execute download commands above"
echo "3. Verify file sizes match estimates"
echo "4. Update COST_TRACKING.md with actual costs"
echo "======================================================================"
echo ""
}
# Run main function
main "$@"