Remove all that nasty html
All checks were successful
Simple Mirror to GitHub / mirror (push) Successful in 11s
All checks were successful
Simple Mirror to GitHub / mirror (push) Successful in 11s
This commit is contained in:
parent
3308e2fae3
commit
8861f112f8
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
build/
|
||||
.direnv/
|
||||
.vscode
|
||||
.vscode
|
||||
html
|
@ -46,6 +46,12 @@ set_target_properties(fastinahurry PROPERTIES
|
||||
CXX_STANDARD_REQUIRED YES
|
||||
)
|
||||
|
||||
add_executable(server ${SRC_FILES} server_main.cc)
|
||||
set_target_properties(server PROPERTIES
|
||||
CXX_STANDARD 23
|
||||
CXX_STANDARD_REQUIRED YES
|
||||
)
|
||||
|
||||
# add_executable(fastinahurry ${SRC_FILES} main.cc)
|
||||
# add_executable(fastinahurry ${SRC_FILES} main.cc)
|
||||
|
||||
@ -62,6 +68,21 @@ target_include_directories(fastinahurry PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR} # For generated *.pb.h
|
||||
)
|
||||
|
||||
target_link_libraries(server PRIVATE
|
||||
trading_grpc_proto
|
||||
nlohmann_json::nlohmann_json
|
||||
${_REFLECTION}
|
||||
${_GRPC_GRPCPP}
|
||||
${_PROTOBUF_LIBPROTOBUF}
|
||||
)
|
||||
|
||||
target_include_directories(server PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_BINARY_DIR} # For generated *.pb.h
|
||||
)
|
||||
|
||||
target_compile_features(server PRIVATE cxx_std_23)
|
||||
|
||||
add_library(trading_grpc_proto
|
||||
${trading_grpc_srcs}
|
||||
${trading_grpc_hdrs}
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
void generate_orders();
|
||||
void process();
|
||||
void start_background_processing();
|
||||
void start_market_data_streaming();
|
||||
grpc::Status send(trading::Order&);
|
||||
bool initialized();
|
||||
void stop();
|
||||
|
@ -3,12 +3,22 @@
|
||||
#include "trading.grpc.pb.h"
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
class Publisher {
|
||||
public:
|
||||
explicit Publisher(std::shared_ptr<grpc::Channel> channel);
|
||||
|
||||
grpc::Status send_order(const trading::Order order);
|
||||
void start_market_data_stream(const std::string& symbol);
|
||||
void stop_market_data_stream();
|
||||
|
||||
private:
|
||||
std::unique_ptr<trading::TradingService::Stub> _stub;
|
||||
std::atomic<bool> _streaming{false};
|
||||
std::thread _stream_thread;
|
||||
|
||||
void stream_market_data(const std::string& symbol);
|
||||
trading::Order generate_order_from_market_data(const trading::MarketData& data);
|
||||
};
|
1
main.cc
1
main.cc
@ -11,7 +11,6 @@ int main(int argc, char* argv[]) {
|
||||
for (uint8_t i = 0; i < argc; i++) {
|
||||
std::printf("argument[%d]: %s\n", i, argv[i]);
|
||||
}
|
||||
assert(argc == 2);
|
||||
Controller ctlr(argc, argv);
|
||||
ctlr.start();
|
||||
|
||||
|
20
server_main.cc
Normal file
20
server_main.cc
Normal file
@ -0,0 +1,20 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
void RunServer(std::string);
|
||||
void print_help() {
|
||||
std::ostringstream ss;
|
||||
ss << "Usage: ./build/server <port>" << std::endl;
|
||||
std::cout << ss.str();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::cout << "Starting gRPC market data server..." << std::endl;
|
||||
if (argc != 2) {
|
||||
print_help();
|
||||
return 1;
|
||||
};
|
||||
RunServer(std::string(argv[1]));
|
||||
|
||||
return 0;
|
||||
}
|
15
src/Algo.cc
15
src/Algo.cc
@ -29,6 +29,10 @@ void Algo::stop() {
|
||||
_stopping.store(true, std::memory_order_release);
|
||||
_running.store(false, std::memory_order_release);
|
||||
|
||||
if (_pub) {
|
||||
_pub->stop_market_data_stream();
|
||||
}
|
||||
|
||||
_reader_thread.request_stop();
|
||||
for (auto& t : _worker_threads) {
|
||||
t.request_stop();
|
||||
@ -84,6 +88,15 @@ void Algo::process() {
|
||||
}
|
||||
}
|
||||
|
||||
void Algo::start_market_data_streaming() {
|
||||
if (!_pub) {
|
||||
std::cerr << "[Error] Publisher not initialized. Call initialize() first." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
_pub->start_market_data_stream("AAPL");
|
||||
}
|
||||
|
||||
void Algo::start_background_processing() {
|
||||
// Thread to read from file source and enqueue
|
||||
_reader_thread = std::jthread([this](std::stop_token stoken) {
|
||||
@ -96,7 +109,7 @@ void Algo::start_background_processing() {
|
||||
}
|
||||
});
|
||||
|
||||
std::size_t num_workers = 2;
|
||||
std::size_t num_workers = 1;
|
||||
for (std::size_t i = 0; i < num_workers; ++i) {
|
||||
_worker_threads.emplace_back([this] (std::stop_token stoken) {
|
||||
while(!stoken.stop_requested()) {
|
||||
|
@ -11,10 +11,12 @@ Controller::Controller(int argc, char* argv[])
|
||||
|
||||
void Controller::start() {
|
||||
if (!_algo->initialized()) _algo->initialize();
|
||||
|
||||
_algo->start_market_data_streaming();
|
||||
|
||||
while(_algo->is_running()) {
|
||||
_algo->process();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
_count++;
|
||||
if (_count > 5) _algo->stop();
|
||||
if (_count >= 10) _algo->stop();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "Publisher.hh"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include <random>
|
||||
|
||||
Publisher::Publisher(std::shared_ptr<grpc::Channel> channel)
|
||||
: _stub(trading::TradingService::NewStub(channel)) {}
|
||||
@ -19,17 +19,78 @@ grpc::Status Publisher::send_order(const trading::Order order) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// void StreamMarketData() {
|
||||
// MarketRequest req;
|
||||
// req.set_symbol("AAPL");
|
||||
void Publisher::start_market_data_stream(const std::string& symbol) {
|
||||
if (_streaming.load()) {
|
||||
std::cout << "Market data stream already running" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
_streaming.store(true);
|
||||
_stream_thread = std::thread(&Publisher::stream_market_data, this, symbol);
|
||||
std::cout << "Started market data stream for " << symbol << std::endl;
|
||||
}
|
||||
|
||||
// ClientContext context;
|
||||
// std::unique_ptr<grpc::ClientReader<MarketData>> reader(
|
||||
// stub_->StreamMarketData(&context, req));
|
||||
void Publisher::stop_market_data_stream() {
|
||||
if (!_streaming.load()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_streaming.store(false);
|
||||
if (_stream_thread.joinable()) {
|
||||
_stream_thread.join();
|
||||
}
|
||||
std::cout << "Stopped market data stream" << std::endl;
|
||||
}
|
||||
|
||||
// MarketData data;
|
||||
// while (reader->Read(&data)) {
|
||||
// std::cout << "Market: " << data.symbol() << " $" << data.price()
|
||||
// << " @ " << data.timestamp() << std::endl;
|
||||
// }
|
||||
// }
|
||||
void Publisher::stream_market_data(const std::string& symbol) {
|
||||
trading::MarketRequest req;
|
||||
req.set_symbol(symbol);
|
||||
|
||||
grpc::ClientContext context;
|
||||
std::unique_ptr<grpc::ClientReader<trading::MarketData>> reader(
|
||||
_stub->StreamMarketData(&context, req));
|
||||
|
||||
trading::MarketData data;
|
||||
while (reader->Read(&data) && _streaming.load()) {
|
||||
std::cout << "Received market data: " << data.symbol()
|
||||
<< " @ $" << data.price()
|
||||
<< " (timestamp: " << data.timestamp() << ")" << std::endl;
|
||||
|
||||
trading::Order order = generate_order_from_market_data(data);
|
||||
grpc::Status status = send_order(order);
|
||||
|
||||
if (!status.ok()) {
|
||||
std::cerr << "[Error] Failed to send order: " << status.error_message() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
grpc::Status status = reader->Finish();
|
||||
if (!status.ok()) {
|
||||
std::cerr << "[Error] Market data stream ended with error: " << status.error_message() << std::endl;
|
||||
}
|
||||
|
||||
_streaming.store(false);
|
||||
}
|
||||
|
||||
trading::Order Publisher::generate_order_from_market_data(const trading::MarketData& data) {
|
||||
trading::Order order;
|
||||
order.set_symbol(data.symbol());
|
||||
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
static std::uniform_int_distribution<> quantity_dist(10, 100);
|
||||
static std::uniform_int_distribution<> side_dist(1, 2);
|
||||
static std::uniform_real_distribution<> price_adjustment(-2.0, 2.0);
|
||||
|
||||
order.set_quantity(quantity_dist(gen));
|
||||
order.set_side(static_cast<trading::Side>(side_dist(gen)));
|
||||
|
||||
double adjusted_price = data.price() + price_adjustment(gen);
|
||||
order.set_price(adjusted_price);
|
||||
|
||||
std::cout << "Generated order: " << (order.side() == trading::BUY ? "BUY" : "SELL")
|
||||
<< " " << order.quantity() << " " << order.symbol()
|
||||
<< " @ $" << order.price() << std::endl;
|
||||
|
||||
return order;
|
||||
}
|
@ -2,6 +2,9 @@
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
using grpc::Server;
|
||||
using grpc::ServerBuilder;
|
||||
@ -26,30 +29,48 @@ class TradingServiceImpl final : public TradingService::Service {
|
||||
|
||||
Status StreamMarketData(ServerContext* ctx, const MarketRequest* req,
|
||||
grpc::ServerWriter<MarketData>* writer) override {
|
||||
std::cout << "Starting market data stream for symbol: " << req->symbol() << std::endl;
|
||||
|
||||
uint32_t max_market_streams = 5;
|
||||
for (uint32_t i = 0; i < max_market_streams; i++) {
|
||||
MarketData data;
|
||||
data.set_symbol(req->symbol());
|
||||
data.set_price(100 + i);
|
||||
data.set_timestamp(time(nullptr));
|
||||
writer->Write(data);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
uint32_t counter = 0;
|
||||
while (!ctx->IsCancelled()) {
|
||||
MarketData data;
|
||||
data.set_symbol(req->symbol());
|
||||
|
||||
double base_price = 100.0;
|
||||
double price_variation = 5.0 * sin(counter * 0.1) + (rand() % 10 - 5) * 0.1;
|
||||
data.set_price(base_price + price_variation);
|
||||
data.set_timestamp(time(nullptr));
|
||||
|
||||
if (!writer->Write(data)) {
|
||||
break;
|
||||
}
|
||||
return Status::OK;
|
||||
|
||||
std::cout << "Sent market data: " << req->symbol()
|
||||
<< " @ $" << data.price() << std::endl;
|
||||
|
||||
counter++;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3));
|
||||
}
|
||||
|
||||
std::cout << "Market data stream ended for: " << req->symbol() << std::endl;
|
||||
return Status::OK;
|
||||
}
|
||||
};
|
||||
|
||||
void RunServer() {
|
||||
std::string addr("0.0.0.0:50051");
|
||||
void RunServer(std::string port) {
|
||||
std::string addr("0.0.0.0");
|
||||
std::string socket = addr;
|
||||
std::ostringstream ss;
|
||||
ss << addr << ":" << port;
|
||||
TradingServiceImpl service;
|
||||
|
||||
ServerBuilder builder;
|
||||
builder.AddListeningPort(addr, grpc::InsecureServerCredentials());
|
||||
|
||||
builder.AddListeningPort(ss.str(), grpc::InsecureServerCredentials());
|
||||
builder.RegisterService(&service);
|
||||
std::unique_ptr<Server> server(builder.BuildAndStart());
|
||||
|
||||
std::cout << "Market server listening on" << addr << std::endl;
|
||||
std::cout << "Market server listening on " << addr << ":" << port << std::endl;
|
||||
|
||||
server->Wait();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user