How to Implement Custom Data Connectors for Fincept’s 100+ Data Sources
Fincept Terminal exposes a plug-in style connector registry that lets you add new data sources by declaring a ConnectorConfig, registering it statically, and implementing a lightweight service that publishes data via the DataHub.
Fincept Terminal manages its extensive ecosystem of data providers through a data-driven connector architecture. Whether you are integrating a proprietary market feed, a cloud time-series database, or an internal REST API, the process follows the same three-layer pattern used by the 100+ built-in sources. This guide walks you through implementing custom data connectors for Fincept using the exact structures found in the repository.
Understanding the Connector Architecture
The Three-Layer Pattern
Every connector in FinceptTerminal is composed of three distinct layers:
- Connector Definition – A declarative
ConnectorConfigobject (ID, UI label, category, input fields, and defaults). - Registration – A static initialization block that pushes the configuration into the global
ConnectorRegistryat program startup. - Data Retrieval – A service (C++ or Python) that communicates with the external system and publishes results via
DataHubfor streaming or returns batch payloads.
This architecture decouples the UI from the implementation. The DataSourcesScreen automatically generates configuration dialogs from the field list, allowing you to swap service implementations without touching interface code.
Key Components
ConnectorRegistry (fincept-qt/src/screens/data_sources/ConnectorRegistry.h)
A singleton that stores all ConnectorConfig objects. Access it via ConnectorRegistry::instance() and call add() to register new connectors.
ConnectorConfig (fincept-qt/src/screens/data_sources/DataSourceTypes.h)
Defines the schema for a connector, including id, name, category, color, and a QVector<FieldConfig> describing UI inputs (URLs, passwords, dropdowns).
DataHub (fincept-qt/src/datahub/DataHub.h)
The internal pub/sub bus. Services publish data using DataHub::instance().publish(topic, QVariant::fromValue(payload)), and consumers (charts, watchlists) subscribe to topics like market:quote:AAPL.
PythonRunner (fincept-qt/src/python/PythonRunner.cpp)
Executes custom Python scripts for data extraction, returning JSON that the C++ side wraps as QVariant. This provides an alternative to writing C++ services.
Step-by-Step Implementation Guide
Step 1 – Define the Connector Configuration
Create a new file in fincept-qt/src/screens/data_sources/connectors/YourConnector.cpp. Define a function that returns a QVector<ConnectorConfig> containing your data source metadata and field definitions.
// IOOPlusConnector.cpp
#include "screens/data_sources/ConnectorRegistry.h"
#include "screens/data_sources/DataSourceTypes.h"
namespace fincept::screens::datasources {
static QVector<ConnectorConfig> ioo_plus_configs() {
return {
{ "ioo-plus",
"IOO+ Data Feed",
"ioo-plus",
Category::MarketData,
"I",
"#009688",
"Custom IOO+ endpoint supporting realtime quotes and historic bars",
true,
false,
{
{"baseUrl", "Base URL", FieldType::Url, "https://api.iooplus.com", true, "", {}},
{"apiKey", "API Key", FieldType::Password, "", true, "", {}},
{"symbols", "Symbols", FieldType::Text, "AAPL,MSFT,GOOGL", false, "", {}},
{"interval", "Interval", FieldType::Select, "", false, "1d",
{ {"1 minute","1m"}, {"5 minutes","5m"}, {"1 hour","1h"}, {"1 day","1d"} } }
}
}
};
}
} // namespace
Step 2 – Register with ConnectorRegistry
Use a static initialization lambda to push your configurations into the registry. This pattern ensures the linker includes your translation unit and the connector appears at startup.
// Add to the same IOOPlusConnector.cpp file
static bool registered = []{
for (auto &c : ioo_plus_configs())
ConnectorRegistry::instance().add(std::move(c));
return true;
}();
This self-registration pattern is identical to the implementation in TimeSeriesDatabases.cpp and MarketData.cpp.
Step 3 – Implement the Data Retrieval Service
Create a service class that handles HTTP requests or WebSocket connections. In fincept-qt/src/services/iooplus/IOOPlusService.cpp:
#include "services/iooplus/IOOPlusService.h"
#include "core/network/http/HttpClient.h"
#include "datahub/DataHub.h"
using namespace fincept::core::network;
namespace fincept::services::iooplus {
void IOOPlusService::fetchQuotes(const QString &baseUrl,
const QString &apiKey,
const QStringList &symbols,
std::function<void(bool, const QJsonArray&)> cb)
{
QUrl url(baseUrl + "/quotes");
QUrlQuery query;
query.addQueryItem("symbols", symbols.join(','));
url.setQuery(query);
HttpClient client;
client.setHeader(QByteArrayLiteral("Authorization"),
QByteArrayLiteral("Bearer ") + apiKey.toUtf8());
client.get(url, [cb](Result<QByteArray> res){
if (!res) { cb(false, {}); return; }
QJsonDocument doc = QJsonDocument::fromJson(*res);
cb(true, doc.array());
});
}
void IOOPlusService::publishQuotes(const QJsonArray "es) {
for (const QJsonValue &v : quotes) {
QString symbol = v.toObject()["symbol"].toString();
QString topic = QStringLiteral("market:quote:%1").arg(symbol);
DataHub::instance().publish(topic, QVariant::fromValue(v.toObject()));
}
}
} // namespace
Alternatively, use the PythonRunner for rapid prototyping by placing a script in fincept-qt/python/ioo_plus_fetcher.py and invoking it via PythonRunner::runScript().
Step 4 – Build and Verify
Add your new files to fincept-qt/CMakeLists.txt:
target_sources(fincept-qt PRIVATE
src/screens/data_sources/connectors/IOOPlusConnector.cpp
src/services/iooplus/IOOPlusService.cpp
)
Build the project, launch Fincept Terminal, and navigate to Settings → Data Sources. Your IOO+ Data Feed connector will appear automatically. Configure the endpoint, save, and trigger a fetch to verify data flows through DataHub to your subscribed screens.
Summary
- Custom data connectors for Fincept are implemented via a declarative
ConnectorConfigobject that defines UI fields and metadata. - Static registration via
ConnectorRegistry::instance().add()ensures connectors self-register at program startup without modifying central lists. - Data retrieval is handled by services (C++ or Python) that communicate with external APIs and publish results through the
DataHubpub/sub system. - Zero UI changes are required; the
DataSourcesScreendynamically generates configuration dialogs from theFieldConfigvector. - Reference implementations in
MarketData.cppandTimeSeriesDatabases.cppprovide proven templates for new connectors.
Frequently Asked Questions
What is the ConnectorRegistry in Fincept Terminal?
The ConnectorRegistry is a singleton class defined in fincept-qt/src/screens/data_sources/ConnectorRegistry.h that stores all available ConnectorConfig objects. It provides static initialization hooks that allow new connectors to self-register at startup by calling ConnectorRegistry::instance().add(), eliminating the need to edit central configuration files when adding new data sources.
Do I need to modify the UI code to add a new data connector?
No. The DataSourcesScreen automatically reads all entries from ConnectorRegistry::instance().all() and constructs the configuration table and dialogs dynamically based on the FieldConfig vector inside each ConnectorConfig. As long as you properly define your fields (URL, password, text, select dropdowns), the UI will render the appropriate input controls without any manual QML or Qt Widgets modifications.
Can I use Python instead of C++ for the data retrieval service?
Yes. Fincept Terminal includes a PythonRunner component in fincept-qt/src/python/PythonRunner.cpp that can execute Python scripts for data extraction and analytics. You can place your integration script in fincept-qt/python/ and invoke it via PythonRunner::runScript(), which returns JSON that the C++ side wraps as QVariant and publishes through DataHub. This is ideal for rapid prototyping or when integrating with Python-native APIs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →