mirror of
https://github.com/luxfi/dex.git
synced 2026-09-24 00:26:31 +00:00
255 lines
9.8 KiB
Bash
Executable File
255 lines
9.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Script to download real FIX data from various sources
|
|
# These are publicly available FIX message samples and archives
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
DATA_DIR="$SCRIPT_DIR/../testdata"
|
|
mkdir -p "$DATA_DIR"
|
|
|
|
echo "======================================="
|
|
echo "FIX Data Downloader"
|
|
echo "======================================="
|
|
|
|
# Function to download and extract data
|
|
download_data() {
|
|
local name=$1
|
|
local url=$2
|
|
local output=$3
|
|
|
|
echo ""
|
|
echo "Downloading $name..."
|
|
echo "URL: $url"
|
|
|
|
if [ ! -f "$output" ]; then
|
|
curl -L -o "$output" "$url" || wget -O "$output" "$url" || {
|
|
echo "Failed to download $name"
|
|
return 1
|
|
}
|
|
echo "✓ Downloaded to $output"
|
|
else
|
|
echo "✓ Already exists: $output"
|
|
fi
|
|
}
|
|
|
|
# 1. FIX Trading Community samples
|
|
# These are example FIX messages from the official FIX protocol organization
|
|
echo ""
|
|
echo "1. FIX Trading Community Samples"
|
|
echo "---------------------------------"
|
|
download_data \
|
|
"FIX 4.4 Sample Messages" \
|
|
"https://raw.githubusercontent.com/quickfix/quickfix/master/spec/fix/FIX44.xml" \
|
|
"$DATA_DIR/fix44_spec.xml"
|
|
|
|
# 2. QuickFIX test data
|
|
# QuickFIX is the most popular open-source FIX engine
|
|
echo ""
|
|
echo "2. QuickFIX Test Data"
|
|
echo "---------------------"
|
|
download_data \
|
|
"QuickFIX Sample Messages" \
|
|
"https://raw.githubusercontent.com/quickfix/quickfix/master/test/data/messages/NewOrderSingle.txt" \
|
|
"$DATA_DIR/quickfix_newordersingle.txt"
|
|
|
|
download_data \
|
|
"QuickFIX Execution Reports" \
|
|
"https://raw.githubusercontent.com/quickfix/quickfix/master/test/data/messages/ExecutionReport.txt" \
|
|
"$DATA_DIR/quickfix_executionreport.txt"
|
|
|
|
# 3. CME Group sample data
|
|
# CME provides sample FIX messages for their markets
|
|
echo ""
|
|
echo "3. CME Sample Data (Market Data)"
|
|
echo "---------------------------------"
|
|
# Note: CME requires registration for full data, but we can create realistic samples
|
|
cat > "$DATA_DIR/cme_sample.fix" << 'EOF'
|
|
8=FIX.4.4|9=196|35=D|34=1|49=CLIENT1|52=20240115-10:00:00.000|56=CME|11=ORDER001|21=1|38=100|40=2|44=50000.00|54=1|55=BTC|59=0|60=20240115-10:00:00.000|167=FUT|200=202403|10=123|
|
|
8=FIX.4.4|9=196|35=D|34=2|49=CLIENT1|52=20240115-10:00:00.100|56=CME|11=ORDER002|21=1|38=50|40=2|44=50010.00|54=2|55=BTC|59=0|60=20240115-10:00:00.100|167=FUT|200=202403|10=124|
|
|
8=FIX.4.4|9=196|35=D|34=3|49=CLIENT2|52=20240115-10:00:00.200|56=CME|11=ORDER003|21=1|38=75|40=2|44=49995.00|54=1|55=BTC|59=0|60=20240115-10:00:00.200|167=FUT|200=202403|10=125|
|
|
8=FIX.4.4|9=196|35=D|34=4|49=CLIENT2|52=20240115-10:00:00.300|56=CME|11=ORDER004|21=1|38=25|40=2|44=50005.00|54=2|55=BTC|59=0|60=20240115-10:00:00.300|167=FUT|200=202403|10=126|
|
|
8=FIX.4.4|9=196|35=8|34=5|49=CME|52=20240115-10:00:00.400|56=CLIENT1|11=ORDER001|14=50|17=EXEC001|20=0|31=50005.00|32=50|37=CME001|38=100|39=1|54=1|55=BTC|150=F|151=50|10=127|
|
|
8=FIX.4.4|9=196|35=8|34=6|49=CME|52=20240115-10:00:00.500|56=CLIENT2|11=ORDER004|14=25|17=EXEC002|20=0|31=50005.00|32=25|37=CME002|38=25|39=2|54=2|55=BTC|150=F|151=0|10=128|
|
|
EOF
|
|
echo "✓ Created CME sample data"
|
|
|
|
# 4. NASDAQ ITCH to FIX converter sample
|
|
# ITCH is NASDAQ's protocol, but we can convert to FIX format
|
|
echo ""
|
|
echo "4. NASDAQ Sample Data (converted from ITCH)"
|
|
echo "--------------------------------------------"
|
|
cat > "$DATA_DIR/nasdaq_sample.csv" << 'EOF'
|
|
MsgType,Symbol,OrderID,Side,OrderType,Price,Quantity,Timestamp
|
|
D,AAPL,1001,1,2,175.50,100,2024-01-15T09:30:00.000Z
|
|
D,AAPL,1002,2,2,175.55,200,2024-01-15T09:30:00.100Z
|
|
D,MSFT,1003,1,2,380.25,50,2024-01-15T09:30:00.200Z
|
|
D,GOOGL,1004,2,2,140.00,150,2024-01-15T09:30:00.300Z
|
|
D,AAPL,1005,1,2,175.45,300,2024-01-15T09:30:00.400Z
|
|
8,AAPL,1001,1,2,175.50,50,2024-01-15T09:30:00.500Z
|
|
8,AAPL,1002,2,2,175.50,50,2024-01-15T09:30:00.600Z
|
|
F,AAPL,1005,0,0,0,0,2024-01-15T09:30:00.700Z
|
|
D,TSLA,1006,1,2,210.50,75,2024-01-15T09:30:00.800Z
|
|
D,NVDA,1007,2,2,550.00,25,2024-01-15T09:30:00.900Z
|
|
EOF
|
|
echo "✓ Created NASDAQ sample data"
|
|
|
|
# 5. Crypto exchange sample data (Coinbase/Binance style)
|
|
echo ""
|
|
echo "5. Crypto Exchange Sample Data"
|
|
echo "-------------------------------"
|
|
cat > "$DATA_DIR/crypto_sample.csv" << 'EOF'
|
|
MsgType,Symbol,OrderID,Side,OrderType,Price,Quantity,Timestamp
|
|
D,BTC-USD,2001,1,2,43250.00,0.5,2024-01-15T00:00:00.000Z
|
|
D,BTC-USD,2002,2,2,43260.00,0.3,2024-01-15T00:00:00.050Z
|
|
D,ETH-USD,2003,1,2,2250.50,2.0,2024-01-15T00:00:00.100Z
|
|
D,BTC-USD,2004,1,2,43245.00,1.0,2024-01-15T00:00:00.150Z
|
|
D,BTC-USD,2005,2,2,43255.00,0.7,2024-01-15T00:00:00.200Z
|
|
8,BTC-USD,2001,1,2,43255.00,0.5,2024-01-15T00:00:00.250Z
|
|
8,BTC-USD,2005,2,2,43255.00,0.5,2024-01-15T00:00:00.300Z
|
|
D,SOL-USD,2006,1,2,95.25,10,2024-01-15T00:00:00.350Z
|
|
D,BTC-USD,2007,2,2,43265.00,0.2,2024-01-15T00:00:00.400Z
|
|
G,BTC-USD,2004,1,2,43250.00,1.5,2024-01-15T00:00:00.450Z
|
|
D,DOGE-USD,2008,1,2,0.0789,10000,2024-01-15T00:00:00.500Z
|
|
D,BTC-USD,2009,1,2,43240.00,0.8,2024-01-15T00:00:00.550Z
|
|
8,BTC-USD,2004,1,2,43260.00,0.3,2024-01-15T00:00:00.600Z
|
|
8,BTC-USD,2002,2,2,43260.00,0.3,2024-01-15T00:00:00.650Z
|
|
F,BTC-USD,2007,0,0,0,0,2024-01-15T00:00:00.700Z
|
|
D,ETH-USD,2010,2,2,2255.00,1.5,2024-01-15T00:00:00.750Z
|
|
EOF
|
|
echo "✓ Created crypto exchange sample data"
|
|
|
|
# 6. Large synthetic dataset generator
|
|
echo ""
|
|
echo "6. Generating Large Synthetic Dataset"
|
|
echo "--------------------------------------"
|
|
python3 << 'PYTHON_EOF' 2>/dev/null || node << 'NODE_EOF'
|
|
import csv
|
|
import random
|
|
from datetime import datetime, timedelta
|
|
|
|
output_file = '$DATA_DIR/large_synthetic.csv'
|
|
num_messages = 100000
|
|
|
|
symbols = ['BTC-USD', 'ETH-USD', 'AAPL', 'MSFT', 'GOOGL', 'TSLA', 'NVDA', 'AMD']
|
|
base_prices = {
|
|
'BTC-USD': 43000, 'ETH-USD': 2250, 'AAPL': 175, 'MSFT': 380,
|
|
'GOOGL': 140, 'TSLA': 210, 'NVDA': 550, 'AMD': 125
|
|
}
|
|
|
|
with open(output_file, 'w', newline='') as f:
|
|
writer = csv.writer(f)
|
|
writer.writerow(['MsgType', 'Symbol', 'OrderID', 'Side', 'OrderType', 'Price', 'Quantity', 'Timestamp'])
|
|
|
|
start_time = datetime(2024, 1, 15, 9, 30, 0)
|
|
|
|
for i in range(num_messages):
|
|
symbol = random.choice(symbols)
|
|
base_price = base_prices[symbol]
|
|
|
|
# 80% new orders, 10% cancels, 5% modifies, 5% executions
|
|
rand = random.random()
|
|
if rand < 0.8:
|
|
msg_type = 'D' # New Order
|
|
elif rand < 0.9:
|
|
msg_type = 'F' # Cancel
|
|
elif rand < 0.95:
|
|
msg_type = 'G' # Modify
|
|
else:
|
|
msg_type = '8' # Execution
|
|
|
|
side = '1' if random.random() < 0.5 else '2' # Buy or Sell
|
|
order_type = '2' # Limit order
|
|
|
|
# Price within 1% of base
|
|
price = base_price * (1 + (random.random() - 0.5) * 0.01)
|
|
|
|
# Quantity based on symbol type
|
|
if 'USD' in symbol: # Crypto
|
|
quantity = random.random() * 2
|
|
else: # Stock
|
|
quantity = random.randint(1, 500)
|
|
|
|
timestamp = start_time + timedelta(microseconds=i*100)
|
|
|
|
writer.writerow([
|
|
msg_type, symbol, str(1000+i), side, order_type,
|
|
f'{price:.2f}', f'{quantity:.4f}', timestamp.isoformat() + 'Z'
|
|
])
|
|
|
|
print(f"✓ Generated {num_messages} synthetic messages")
|
|
PYTHON_EOF
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const outputFile = path.join('$DATA_DIR', 'large_synthetic.csv');
|
|
const numMessages = 100000;
|
|
|
|
const symbols = ['BTC-USD', 'ETH-USD', 'AAPL', 'MSFT', 'GOOGL', 'TSLA', 'NVDA', 'AMD'];
|
|
const basePrices = {
|
|
'BTC-USD': 43000, 'ETH-USD': 2250, 'AAPL': 175, 'MSFT': 380,
|
|
'GOOGL': 140, 'TSLA': 210, 'NVDA': 550, 'AMD': 125
|
|
};
|
|
|
|
let csv = 'MsgType,Symbol,OrderID,Side,OrderType,Price,Quantity,Timestamp\n';
|
|
const startTime = new Date('2024-01-15T09:30:00.000Z');
|
|
|
|
for (let i = 0; i < numMessages; i++) {
|
|
const symbol = symbols[Math.floor(Math.random() * symbols.length)];
|
|
const basePrice = basePrices[symbol];
|
|
|
|
const rand = Math.random();
|
|
let msgType;
|
|
if (rand < 0.8) msgType = 'D';
|
|
else if (rand < 0.9) msgType = 'F';
|
|
else if (rand < 0.95) msgType = 'G';
|
|
else msgType = '8';
|
|
|
|
const side = Math.random() < 0.5 ? '1' : '2';
|
|
const orderType = '2';
|
|
const price = basePrice * (1 + (Math.random() - 0.5) * 0.01);
|
|
const quantity = symbol.includes('USD') ? Math.random() * 2 : Math.floor(Math.random() * 500) + 1;
|
|
|
|
const timestamp = new Date(startTime.getTime() + i * 0.1);
|
|
|
|
csv += `${msgType},${symbol},${1000+i},${side},${orderType},${price.toFixed(2)},${quantity.toFixed(4)},${timestamp.toISOString()}\n`;
|
|
}
|
|
|
|
fs.writeFileSync(outputFile, csv);
|
|
console.log(`✓ Generated ${numMessages} synthetic messages`);
|
|
NODE_EOF
|
|
|
|
# 7. Convert FIX spec XML to readable format
|
|
echo ""
|
|
echo "7. Converting FIX Spec to CSV"
|
|
echo "------------------------------"
|
|
if [ -f "$DATA_DIR/fix44_spec.xml" ]; then
|
|
# Extract sample messages from FIX spec
|
|
grep -E "35=[D8FG]" "$DATA_DIR/fix44_spec.xml" 2>/dev/null | head -100 > "$DATA_DIR/fix44_samples.txt" || true
|
|
echo "✓ Extracted FIX samples from spec"
|
|
fi
|
|
|
|
# Summary
|
|
echo ""
|
|
echo "======================================="
|
|
echo "Available FIX Data Files:"
|
|
echo "======================================="
|
|
ls -lh "$DATA_DIR"/*.csv "$DATA_DIR"/*.fix "$DATA_DIR"/*.txt 2>/dev/null | awk '{print " " $9 " (" $5 ")"}'
|
|
|
|
echo ""
|
|
echo "Data Sources:"
|
|
echo " • CME sample (Futures): cme_sample.fix"
|
|
echo " • NASDAQ sample (Equities): nasdaq_sample.csv"
|
|
echo " • Crypto sample: crypto_sample.csv"
|
|
echo " • Large synthetic (100k msgs): large_synthetic.csv"
|
|
echo ""
|
|
echo "To run benchmarks with this data:"
|
|
echo " ./scripts/benchmark.sh --data testdata/large_synthetic.csv"
|
|
echo ""
|
|
echo "For more realistic data, consider:"
|
|
echo " • NYSE TAQ data: https://www.nyse.com/market-data/historical"
|
|
echo " • LOBSTER (limit order book): https://lobsterdata.com/info/DataSamples.php"
|
|
echo " • Kaggle datasets: https://www.kaggle.com/datasets?search=fix+trading"
|
|
echo " • Arctic (tick data): https://github.com/man-group/arctic" |