Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,25 @@ if(OPTIONX_BUILD_EXAMPLES)
)
endif()

add_executable(telegram_signal_bridge_smoke examples/telegram_signal_bridge_smoke.cpp)
target_compile_features(telegram_signal_bridge_smoke PRIVATE cxx_std_17)
target_include_directories(telegram_signal_bridge_smoke PRIVATE
${EXAMPLE_INCLUDE_DIRS}
${EXAMPLE_DEPS_INCLUDE_DIRS}
)
target_link_directories(telegram_signal_bridge_smoke PRIVATE ${EXAMPLE_LIBRARY_DIRS})
target_compile_definitions(
telegram_signal_bridge_smoke PRIVATE
${EXAMPLE_DEFINES}
LOGIT_BASE_PATH="${LOGIT_BASE_PATH_FWD}"
)
if(MINGW)
target_compile_options(telegram_signal_bridge_smoke PRIVATE -Wa,-mbig-obj)
elseif(MSVC)
target_compile_options(telegram_signal_bridge_smoke PRIVATE /bigobj)
endif()
target_link_libraries(telegram_signal_bridge_smoke PRIVATE ${EXAMPLE_LIBS} optionx_cpp)

add_executable(protocol_v1_bridge_smoke examples/protocol_v1_bridge_smoke.cpp)
target_compile_features(protocol_v1_bridge_smoke PRIVATE cxx_std_17)

Expand Down
4 changes: 4 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ Currently maintained examples:
- `protocol_v1_named_pipe_bridge_smoke.cpp` starts Bridge Protocol v1 over a
local named pipe and, on Windows, can run `--self-test` with a local pipe
client.
- `telegram_signal_bridge_smoke.cpp` demonstrates the Telegram parser and live
bridge lifecycle with a deterministic in-memory source. The production
source boundary can be backed by `tg-client-stdio`; this example needs no
Telegram credentials.
- `metatrader_file_bridge_smoke.cpp` runs the C++ side of the MetaTrader
Common\Files bridge against a temporary command/event layout.
- `metatrader_file_command_writer_smoke.cpp` demonstrates the C++ command-writer
Expand Down
113 changes: 113 additions & 0 deletions examples/telegram_signal_bridge_smoke.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/// \file telegram_signal_bridge_smoke.cpp
/// \brief Demonstrates Telegram parsing and bridge dispatch with a fake source.

#include <optionx_cpp/bridges/telegram.hpp>

#include <iostream>
#include <memory>
#include <string>
#include <utility>

namespace {

class DemoMessageSource final
: public optionx::bridges::telegram::TelegramMessageSource {
public:
bool start(message_callback_t on_message, error_callback_t on_error) override;
void stop() noexcept override;
void emit(const optionx::bridges::telegram::TelegramRawMessage& message);

private:
message_callback_t m_on_message;
};

std::unique_ptr<optionx::bridges::telegram::TelegramSignalBridgeConfig>
make_config();

optionx::bridges::telegram::TelegramRawMessage make_message(
std::string text,
std::int64_t message_id);

} // namespace

int main() {
// The production source can be an adapter around tg-client-stdio. A fake
// source keeps this example deterministic and runnable without Telegram
// credentials or an authorized session.
auto source = std::make_shared<DemoMessageSource>();
optionx::bridges::telegram::TelegramSignalBridge bridge(source);
if (!bridge.configure(make_config())) {
std::cerr << "failed to configure Telegram bridge\n";
return 1;
}

std::int64_t next_signal_id = 0;
bridge.on_signal_id() = [&next_signal_id]() {
return ++next_signal_id;
};
bridge.on_status_update() = [](const optionx::BridgeStatusUpdate& update) {
std::cout << "status=" << optionx::to_str(update.status);
if (!update.message.empty()) {
std::cout << " message=" << update.message;
}
std::cout << '\n';
};
bridge.on_signal_report() = [](const optionx::BridgeSignalReport& report) {
std::cout << "report=" << report.reason_code
<< " status=" << optionx::to_str(report.status) << '\n';
};
bridge.on_trade_signal() = [](std::unique_ptr<optionx::TradeSignal> signal) {
std::cout << "signal=" << signal->symbol
<< " direction=" << optionx::to_str(signal->order_type)
<< " duration=" << signal->duration
<< " id=" << signal->signal_id << '\n';
};

bridge.run();
source->emit(make_message("EURUSD BUY 5m", 1));
source->emit(make_message("EURUSD BUY 5m", 1));
bridge.shutdown();
return 0;
}

namespace {

bool DemoMessageSource::start(message_callback_t on_message, error_callback_t on_error) {
(void)on_error;
m_on_message = std::move(on_message);
return true;
}

void DemoMessageSource::stop() noexcept {
m_on_message = {};
}

void DemoMessageSource::emit(
const optionx::bridges::telegram::TelegramRawMessage& message) {
if (m_on_message) {
m_on_message(message);
}
}

std::unique_ptr<optionx::bridges::telegram::TelegramSignalBridgeConfig>
make_config() {
auto config = std::make_unique<
optionx::bridges::telegram::TelegramSignalBridgeConfig>();
config->bridge_id = 9001;
config->fixed_amount = 1.0;
return config;
}

optionx::bridges::telegram::TelegramRawMessage make_message(
std::string text,
const std::int64_t message_id) {
optionx::bridges::telegram::TelegramRawMessage message;
message.chat_id = "demo-signals";
message.chat_title = "Demo Telegram Signals";
message.message_id = message_id;
message.date_ms = 1800000000000;
message.text = std::move(text);
return message;
}

} // namespace
Loading