- Overview
- Architecture
- API Integration
- WebSocket Implementation
- Data Flow
- Plugin Components
- Configuration Management
- Error Handling
- Performance Optimization
- Building and Deployment
The OpenAlgo AmiBroker Plugin is a sophisticated data plugin that bridges AmiBroker with OpenAlgo's comprehensive broker integration platform. It provides real-time and historical market data from multiple Indian brokers through a unified API interface.
- Real-time Quote Streaming: WebSocket-based live market data
- Historical Data Backfill: Intelligent data retrieval with caching
- Multi-Exchange Support: NSE, BSE, MCX, and other Indian exchanges
- Authentication: Secure API key-based authentication
- Auto-Reconnection: Robust connection management with retry logic
- Performance Optimized: Efficient data caching and minimal latency
┌─────────────────┐
│ AmiBroker │
│ Application │
└────────┬────────┘
│
Plugin API
│
┌────────▼────────┐
│ OpenAlgo │
│ Plugin DLL │
├─────────────────┤
│ • Plugin.cpp │
│ • ConfigDlg.cpp │
│ • WebSocket │
│ • HTTP Client │
└────────┬────────┘
│
Network Layer
│
┌────┴────┐
│ │
HTTP API WebSocket
│ │
┌───▼─────────▼───┐
│ OpenAlgo │
│ Server │
├─────────────────┤
│ • REST API │
│ • WebSocket Hub │
│ • Broker APIs │
└─────────────────┘
│
Broker APIs
│
┌────────▼────────┐
│ Indian Brokers │
│ (Zerodha, etc.) │
└─────────────────┘
- Type: Data Plugin (PLUGIN_TYPE_DATA)
- Version: 10003
- Plugin ID: PIDCODE('O', 'A', 'L', 'G')
- Minimum AmiBroker Version: 5.30.0
Endpoint: /api/v1/ping
Method: POST
Purpose: Verify server connectivity and authentication
Request Body:
{
"apikey": "your_api_key"
}Response:
{
"status": "success",
"message": "pong",
"broker": "zerodha"
}Endpoint: /api/v1/quotes
Method: POST
Purpose: Fetch real-time Level 1 quotes
Request Body:
{
"apikey": "your_api_key",
"symbol": "RELIANCE",
"exchange": "NSE"
}Response:
{
"status": "success",
"data": {
"ltp": 2450.50,
"open": 2440.00,
"high": 2455.00,
"low": 2435.00,
"volume": 1234567,
"oi": 0,
"prev_close": 2445.00
}
}Endpoint: /api/v1/history
Method: POST
Purpose: Retrieve historical OHLCV data
Request Body:
{
"apikey": "your_api_key",
"symbol": "RELIANCE",
"exchange": "NSE",
"interval": "1m",
"start_date": "2024-01-01",
"end_date": "2024-01-31"
}Response:
{
"status": "success",
"data": [
{
"timestamp": 1704096600,
"open": 2440.00,
"high": 2442.00,
"low": 2438.00,
"close": 2441.00,
"volume": 12345,
"oi": 0
}
]
}1m- 1 minute (intraday)D- Daily (End of Day)
- TCP Connection: Establish socket connection to WebSocket server
- HTTP Upgrade: Send WebSocket upgrade request
- Authentication: Send API key for authentication
- Subscription: Subscribe to required symbols
- Data Reception: Receive and process market data frames
{
"action": "authenticate",
"api_key": "your_api_key"
}{
"action": "subscribe",
"symbol": "RELIANCE",
"exchange": "NSE",
"mode": 2
}{
"type": "market_data",
"symbol": "RELIANCE",
"exchange": "NSE",
"ltp": 2450.50,
"volume": 1234567
}- FIN: 1 (Final frame)
- OpCode: 0x01 (Text frame)
- Mask: 1 (Client must mask)
- Payload: JSON message
- Ping Interval: 30 seconds
- Reconnection Delay: 10 seconds
- Timeout: 5 seconds for operations
- Non-blocking Mode: After initial handshake
- AmiBroker calls
GetRecentInfo()for symbol - Plugin checks WebSocket subscription status
- If not subscribed, sends subscription request
- Processes incoming WebSocket data
- Updates quote cache
- Returns
RecentInfostructure to AmiBroker
- AmiBroker calls
GetQuotesEx()with parameters - Plugin determines data range:
- Initial load: 30 days for 1m, 1 year for daily
- Refresh: Today's data only
- Sends HTTP request to history endpoint
- Parses JSON response
- Converts timestamps to AmiBroker format
- NEW (v1.0.0): Normalizes timestamps for 1-minute bars
- Sets Second, MilliSec, MicroSec to 0
- Prevents "freak candles" during live updates
- Handles duplicates intelligently
- NEW (v1.0.0): Sorts quotes chronologically using qsort()
- Ensures proper timestamp order
- Fixes mixed-up timestamps in Quote Editor
- Returns sorted quote array to AmiBroker
- Main plugin implementation
- AmiBroker API functions
- Data retrieval logic
- WebSocket management
- Quote caching system
- Configuration dialog implementation
- Connection testing functionality
- Settings persistence
- WebSocket testing
- DLL initialization
- MFC application setup
- Registry key management
- Global variable declarations
- Server configuration
- API keys
- Status management
Returns plugin metadata to AmiBroker
- Initializes plugin
- Loads configuration
- Sets up WebSocket
- Initializes quote cache
- Retrieves historical data
- Manages data backfill
- Handles different periodicities
- Provides real-time quotes
- Manages WebSocket subscriptions
- Updates quote window
- Reports connection status
- Updates status LED
- Provides error messages
- Opens configuration dialog
- Tests connections
- Saves settings
Location: HKEY_CURRENT_USER\Software\OpenAlgo
Settings:
Server: OpenAlgo server addressApiKey: Authentication API keyWebSocketUrl: WebSocket server URLPort: HTTP API portRefreshInterval: Data refresh intervalTimeShift: Time zone adjustment
- Server connection testing
- WebSocket connection testing
- Live quote display during test
- Input validation
- Secure API key storage
- STATUS_WAIT (Yellow): Waiting to connect
- STATUS_CONNECTED (Green): Successfully connected
- STATUS_DISCONNECTED (Red): Connection failed, will retry
- STATUS_SHUTDOWN (Purple): Offline, manual reconnect required
- Initial Retry Count: 8 attempts
- Retry Interval: 15 seconds
- Exponential Backoff: No (fixed interval)
- Manual Reconnect: Via right-click menu
- Automatic reconnection on disconnect
- WebSocket fallback to HTTP API
- Cache preservation during disconnects
- Duplicate data handling
- Quote Cache: 5-second TTL for real-time quotes
- Hash Table Size: 997 buckets (prime number)
- WebSocket Priority: Prefer WebSocket over HTTP
- Batch Operations: Process multiple symbols efficiently
- Intelligent Backfill: Only fetch missing data
- Duplicate Detection: Compare timestamps within 60 seconds
- Incremental Updates: Refresh only today's data
- Non-blocking I/O: WebSocket uses async operations
- Timestamp Normalization (v1.0.0): 1-minute bars normalized to prevent duplicates
- Chronological Sorting (v1.0.0): Automatic qsort() after data merge
- Dynamic Allocation: Based on data size
- Cleanup on Disconnect: Release resources properly
- Buffer Limits: 4KB for WebSocket frames
- Response Truncation: 30KB max for HTTP responses
- Visual Studio 2019 or later
- Windows SDK
- MFC libraries
- AmiBroker SDK headers
- Platform: x64 (64-bit)
- Configuration: Release
- Runtime Library: Multi-threaded DLL
- Character Set: Unicode
- Build the plugin in Release mode
- Copy
OpenAlgo.dllto AmiBroker Plugins folder - Restart AmiBroker
- Configure via File > Database Settings
- Enter API credentials
- Test connection
- WinSock2: WebSocket implementation
- WinInet: HTTP client
- MFC: Dialog and UI components
- CRT: C++ runtime
- Stored in Windows Registry
- Never logged or displayed in plain text
- Transmitted over secure channels
- Validated on each request
- Support for WSS (WebSocket Secure)
- HTTPS support for API calls
- Input validation
- Buffer overflow protection
-
Connection Failed
- Verify server URL and port
- Check API key validity
- Ensure firewall allows connections
- Verify OpenAlgo server is running
-
No Data Received
- Check market hours
- Verify symbol format (SYMBOL-EXCHANGE)
- Ensure subscription is active
- Check WebSocket connection status
-
WebSocket Disconnects
- Network instability
- Server timeout
- Authentication failure
- Check ping/pong mechanism
- Status LED color indicates connection state
- Right-click status area for manual control
- Check AmiBroker log for errors
- Use configuration dialog test buttons
Location: Plugin.cpp:708-717
Problem: "Freak candles" appeared during live updates due to varying seconds in timestamps
Solution: Normalize Second, MilliSec, MicroSec fields to 0 for 1-minute bars
if (nPeriodicity == 60) // 1-minute data
{
pQuotes[quoteIndex].DateTime.PackDate.Second = 0;
pQuotes[quoteIndex].DateTime.PackDate.MilliSec = 0;
pQuotes[quoteIndex].DateTime.PackDate.MicroSec = 0;
}Location: Plugin.cpp:123-139, 880-886
Problem: Timestamps mixed up when filling data gaps
Solution: Added qsort() with custom comparator after data merge
int CompareQuotations(const void* a, const void* b)
{
const struct Quotation* qa = (const struct Quotation*)a;
const struct Quotation* qb = (const struct Quotation*)b;
if (qa->DateTime.Date < qb->DateTime.Date) return -1;
else if (qa->DateTime.Date > qb->DateTime.Date) return 1;
else return 0;
}Location: OpenAlgoConfigDlg.cpp:503-541
Problem: Unicode characters displayed as garbled text
Solution: Removed Unicode icons, use simple text messages
- Support for more intervals (5m, 15m, 1h)
- Tick-by-tick data support
- Options chain data
- Market depth (Level 2) data
- Compression for large datasets
- SSL/TLS certificate validation
- Connection pooling
- Data compression
- Binary protocol support
- Multi-threaded operations
- Advanced caching strategies
- OpenAlgo Documentation: https://docs.openalgo.in/
- AmiBroker Plugin SDK: AmiBroker ADK documentation
- GitHub Repository: Plugin source code and issues
- OpenAlgo Forums
- GitHub Issues
- Discord/Telegram groups
This documentation is maintained by the OpenAlgo community. For updates and contributions, please visit the GitHub repository.