Market Data Service is a high-performance financial data API that provides comprehensive Symbol prices of different markets through both RESTful endpoints and real-time WebSocket connections.
|
|
3 mēneši atpakaļ | |
|---|---|---|
| MT5 | 3 mēneši atpakaļ | |
| config | 3 mēneši atpakaļ | |
| docs | 4 mēneši atpakaļ | |
| migrations | 4 mēneši atpakaļ | |
| models | 4 mēneši atpakaļ | |
| src | 3 mēneši atpakaļ | |
| tests | 3 mēneši atpakaļ | |
| .gitignore | 4 mēneši atpakaļ | |
| README.md | 3 mēneši atpakaļ | |
| ecosystem.config.js | 3 mēneši atpakaļ | |
| package-lock.json | 3 mēneši atpakaļ | |
| package.json | 3 mēneši atpakaļ | |
| schema.sql | 4 mēneši atpakaļ |
A high-performance financial data API that provides comprehensive market data for various financial instruments including cryptocurrencies, stocks, forex, and commodities through both RESTful endpoints and real-time WebSocket connections.
The service includes an MT5 Expert Advisor (EA) that automatically sends historical candle data and live tick prices to the API.
MT5/Experts/MarketDataSender.mq5 to your MT5 Experts directoryConfigure EA settings:
ApiBaseUrl: Your API endpoint (e.g., http://your-server:3000)ApiKey: Optional authentication keyHistoricalCandleCount: Number of historical candles to send (default: 1000)HistoricalTimeframe: Timeframe for historical data (default: H1)Attach the EA to any MT5 chart
The EA will:
EXCHANGE_SYMBOL)✅ MT5 Integration
✅ Data Integrity
✅ Reliability
Comprehensive test coverage
Multi-Asset Support: Handles cryptocurrencies, stocks, forex, and commodities
Real-time Data: Live price feeds with bid/ask spreads
Historical Data: OHLCV candle data with flexible timeframes
RESTful API: Well-structured endpoints for all operations
Data Validation: Comprehensive input validation using Joi
Error Handling: Robust error handling with detailed responses
Security: Helmet.js for security headers, CORS support
Logging: Winston-based logging with multiple transports
Database: PostgreSQL with Sequelize ORM
Scalable Architecture: Modular design with controllers, routes, and middleware
market-data-service/
├── src/
│ ├── config/
│ │ └── database.js # Database configuration
│ ├── controllers/
│ │ ├── symbolController.js # Symbol CRUD operations
│ │ ├── candleController.js # Candle data operations
│ │ └── livePriceController.js # Live price operations
│ ├── middleware/
│ │ ├── errorHandler.js # Global error handling
│ │ └── validation.js # Request validation
│ ├── models/
│ │ ├── Symbol.js # Symbol model
│ │ ├── Candle1h.js # 1-hour candle model
│ │ ├── LivePrice.js # Live price model
│ │ └── index.js # Model associations
│ ├── routes/
│ │ ├── symbols.js # Symbol routes
│ │ ├── candles.js # Candle routes
│ │ └── livePrices.js # Live price routes
│ ├── utils/
│ │ └── logger.js # Logging utility
│ ├── app.js # Express app configuration
│ └── server.js # Server startup
├── tests/ # Test files
├── schema.sql # Database schema
├── .env # Environment variables
├── .gitignore # Git ignore rules
├── package.json # Dependencies and scripts
└── README.md # This file
Database Constraints
ALTER TABLE candles_1h
ADD CONSTRAINT unique_symbol_open_time
UNIQUE (symbol_id, open_time);
Precision Requirements
// All numeric fields require 15 decimal precision
Joi.number().precision(15)
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install required tools
sudo apt install -y curl wget git htop nano ufw
# Using NodeSource repository
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# Verify installation
node --version # Should show v18.x.x
npm --version # Should show latest version
# Install PostgreSQL
sudo apt install -y postgresql postgresql-contrib
# Start and enable PostgreSQL
sudo systemctl enable postgresql
sudo systemctl start postgresql
# Verify installation
psql --version # Should show 15.x or higher
# Create application directory
sudo mkdir -p /root/market-data-service
sudo chown $USER:$USER /root/market-data-service
cd /root/market-data-service
# Clone repository (replace with your actual repo URL)
git clone https://git.mqldevelopment.com/muhammad.uzair/market-data-service.git .
# OR copy your project files to this directory
# Install dependencies
npm install --production
# Set up environment variables
cat > .env << EOF
DB_TYPE=postgres
DB_HOST=localhost
DB_PORT=5432
DB_NAME=financial_data
DB_USER=postgres
DB_PASSWORD=your_secure_password_here
PORT=3001
NODE_ENV=production
JWT_SECRET=your_secure_jwt_secret_key_here
CORS_ORIGIN=*
LOG_LEVEL=info
EOF
# Switch to postgres user
sudo -u postgres psql
# In PostgreSQL shell, run:
CREATE DATABASE financial_data;
ALTER USER postgres PASSWORD 'your_secure_password_here';
GRANT ALL PRIVILEGES ON DATABASE financial_data TO postgres;
\q
# Exit and run migrations
npx sequelize-cli db:migrate
# Verify tables were created
sudo -u postgres psql -d financial_data -c "\dt"
# Install PM2 globally
sudo npm install -g pm2
# Create PM2 ecosystem file
cat > ecosystem.config.js << EOF
module.exports = {
apps: [{
name: 'market-data-api',
script: 'src/server.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3001
},
error_file: './logs/err.log',
out_file: './logs/out.log',
log_file: './logs/combined.log',
time: true,
merge_logs: true,
watch: false,
max_memory_restart: '1G'
}]
};
EOF
# Start with PM2
pm2 start ecosystem.config.js
pm2 save
pm2 startup
# Verify PM2 status
pm2 status
pm2 logs
# Copy nginx configuration
sudo cp nginx-1.24.0/conf/nginx.conf /etc/nginx/nginx.conf
# Test configuration
sudo nginx -t
# Start Nginx
sudo systemctl enable nginx
sudo systemctl start nginx
# Install certbot
sudo apt install -y certbot python3-certbot-nginx
# Generate SSL certificate
sudo certbot --nginx -d your-domain.com
# Test certificate
sudo certbot certificates
# Update nginx configuration with SSL
sudo tee /etc/nginx/sites-available/market-data-api << EOF
server {
listen 80;
server_name your-domain.com;
# Redirect HTTP to HTTPS
return 301 https://\$server_name\$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
# API Proxy Settings
location /api/ {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
# Timeout and buffer settings
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
client_max_body_size 50M;
}
location /health {
proxy_pass http://localhost:3001/health;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
location / {
return 200 "Market Data API is running. Use /api/ for endpoints\\n";
add_header Content-Type text/plain;
}
}
EOF
# Enable site and restart nginx
sudo ln -s /etc/nginx/sites-available/market-data-api /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl restart nginx
# Test HTTP to HTTPS redirect
curl -I http://your-domain.com
# Test HTTPS API endpoints
curl https://your-domain.com/health
curl https://your-domain.com/api/health
curl https://your-domain.com/api/symbols
# Test bulk endpoint
curl -X POST https://your-domain.com/api/live-prices/bulk \
-H "Content-Type: application/json" \
-d '{"prices": [{"symbolId": 1, "price": 123.45}]}'
This section explains how to run the project locally on your development machine.
# Clone from GitHub
git clone https://git.mqldevelopment.com/muhammad.uzair/market-data-service.git
cd market-data-service
# Install dependencies
npm install
# Create local database
createdb financial_data
# Set up environment variables
cat > .env << EOF
DB_TYPE=postgres
DB_HOST=localhost
DB_PORT=5432
DB_NAME=financial_data
DB_USER=your_local_username
DB_PASSWORD=your_local_password
PORT=3001
NODE_ENV=development
JWT_SECRET=your_development_jwt_secret_key
CORS_ORIGIN=http://localhost:3000
LOG_LEVEL=debug
EOF
# Install Sequelize CLI (if not already installed)
npm install -g sequelize-cli
# Run migrations to create tables
npx sequelize-cli db:migrate
# Verify tables were created
psql -d financial_data -c "\dt"
# Option 1: Using npm script (recommended)
npm run dev
# Option 2: Using nodemon directly
npx nodemon src/server.js
# Option 3: Using node directly
node src/server.js
# Test health endpoint
curl http://localhost:3001/health
# Test API endpoints
curl http://localhost:3001/api/symbols
curl http://localhost:3001/api/live-prices
# Test bulk endpoint
curl -X POST http://localhost:3001/api/live-prices/bulk \
-H "Content-Type: application/json" \
-d '{"prices": [{"symbolId": 1, "price": 123.45}]}'
# Navigate to project directory
cd /root/market-data-service
# Stop the application
pm2 stop market-data-api
# Backup current deployment (optional but recommended)
cp .env .env.backup
cp ecosystem.config.js ecosystem.config.js.backup
# Pull latest changes
git pull origin master
# Install any new dependencies
npm install --production
# Run database migrations (if schema changed)
npx sequelize-cli db:migrate
# Restart application
pm2 start ecosystem.config.js
pm2 save
# Verify everything is working
pm2 status
curl https://your-domain.com/health
# Navigate to project directory
cd /root/market-data-service
# Create backup
sudo cp -r /root/market-data-service /root/market-data-service-backup-$(date +%Y%m%d_%H%M%S)
# Stop services
pm2 stop market-data-api
sudo systemctl stop nginx
# Update code
git fetch origin
git reset --hard origin/master
# Install dependencies
npm install --production
# Update environment if needed
nano .env
# Run migrations
npx sequelize-cli db:migrate
# Update PM2 configuration if needed
pm2 start ecosystem.config.js
pm2 save
# Restart nginx
sudo systemctl start nginx
# Verify deployment
pm2 status
sudo systemctl status nginx
curl https://your-domain.com/health
Error: ERROR: role "postgres" already exists
Solution:
# Just set password for existing user
sudo -u postgres psql
ALTER USER postgres PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE financial_data TO postgres;
\q
Error: cannot load certificate "/etc/letsencrypt/live/.../fullchain.pem"
Solution:
# Generate certificate first
sudo certbot --nginx -d your-domain.com
# Check if certificates exist
ls -la /etc/letsencrypt/live/your-domain.com/
# Test nginx configuration
sudo nginx -t
Question: Why are there 8 instances running?
Answer: This is GOOD for production:
To adjust instances:
pm2 scale market-data-api 4 # Use 4 instances
pm2 scale market-data-api 1 # Use 1 instance for testing
# Check service status
pm2 status
sudo systemctl status nginx
sudo systemctl status postgresql
# View logs
pm2 logs --lines 50
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
# Check renewal status
sudo certbot certificates
sudo systemctl status certbot.timer
# Manual renewal test
sudo certbot renew --dry-run
pm2 status # Check status
pm2 logs # View logs
pm2 monit # Real-time monitoring
pm2 restart all # Restart all apps
pm2 stop all # Stop all apps
pm2 delete all # Delete all apps
sudo systemctl status nginx # Check status
sudo systemctl restart nginx # Restart nginx
sudo nginx -t # Test configuration
sudo tail -f /var/log/nginx/error.log # View error logs
# Connect to database
sudo -u postgres psql -d financial_data
# View tables
\dt
# View table structure
\d table_name
# Backup database
pg_dump financial_data > backup.sql
# Restore database
psql financial_data < backup.sql
Create a .env file in the root directory with the following variables:
# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=market_data
DB_USER=your_username
DB_PASSWORD=your_password
# Server Configuration
PORT=3000
NODE_ENV=development
# JWT Configuration (if needed for authentication)
JWT_SECRET=your_jwt_secret_key
# API Keys (if needed for external services)
# BINANCE_API_KEY=your_api_key
# BINANCE_API_SECRET=your_api_secret
# CORS Configuration
CORS_ORIGIN=*
GET /health - Check service healthGET /api/symbols - Get all symbols (with filtering)GET /api/symbols/search?q=EURUSD - Search symbols by nameGET /api/symbols/:id - Get symbol by IDPOST /api/symbols - Create new symbolPUT /api/symbols/:id - Update symbolDELETE /api/symbols/:id - Delete symbol (soft delete)GET /api/candles?symbolId=1&startTime=2025-01-01T00:00:00Z&endTime=2025-01-02T00:00:00Z&limit=100&offset=0 - Get candles with filteringGET /api/candles/ohlc?symbolId=1&period=1h&limit=100 - Get OHLC dataGET /api/candles/:symbolId/latest - Get latest candle for symbolPOST /api/candles - Create new candlePOST /api/candles/bulk - Bulk create candlesDELETE /api/candles/cleanup/:symbolId?keep=1000 - Clean up old candles, keep latest N (default 1000)GET /api/live-prices - Get all live pricesGET /api/live-prices/exchange/:exchange - Get live prices by exchangeGET /api/live-prices/type/:type - Get live prices by instrument typeGET /api/live-prices/:symbolId - Get live price for symbolPOST /api/live-prices - Create/update live pricePOST /api/live-prices/bulk - Bulk update live pricesDELETE /api/live-prices/:symbolId - Delete live pricenpm start - Start production servernpm run dev - Start development server with auto-reloadnpm test - Run Jest test suitenpm run test:watch - Run tests in watch modenpm run migrate - Run database migrationsnpm run migrate:undo - Revert last migrationnpm run lint - Run ESLintnpm run lint:fix - Fix ESLint issuesWe use Sequelize CLI for database migrations:
# Create new migration
npx sequelize-cli migration:generate --name your-migration-name
# Run pending migrations
npx sequelize-cli db:migrate
# Revert last migration
npx sequelize-cli db:migrate:undo
NODE_ENV=production in your environmentnpm start to start the production server