Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfce23a33d | ||
|
|
709334a1aa |
No files matched your search
@@ -116,7 +116,7 @@
|
||||
_timer.start();
|
||||
_analytics_service.archive_theos(archived_theos);
|
||||
_timer.stop();
|
||||
Log.Gen.info($"SingleVolSurfaceGateway._on_bb_data archiving theos vs_id: {_volsurface_id} size: " +
|
||||
Log.Gen.info($"SingleVolSurfaceGateway._on_bb_data archiving theos size: " +
|
||||
$"{archived_theos.SecTheo.Count} time: {_timer.lastIntervalTime} msecs");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
||||
@@ -60,8 +60,6 @@ namespace mbts.spark {
|
||||
|
||||
private IReadOnlyDictionary<string, OptionTheoInterpolationData>
|
||||
_filter_for_publish(IReadOnlyDictionary<string, OptionTheoInterpolationData> all_theos) {
|
||||
// find the symbol vs vs_id, get the committed vs, see if it is
|
||||
// owned by the current user, and only then publish it
|
||||
HashSet<string> syms = new HashSet<string>();
|
||||
VolSurfaceUsageListImmutable usage = _bb.read_state(SparkTags.VolSurfaceUsageTag);
|
||||
string current_user = _bb.read_state(SparkTags.CurrentUser).name;
|
||||
@@ -71,7 +69,7 @@ namespace mbts.spark {
|
||||
if (vs_input != null) {
|
||||
if (vs_input.surface_settings.core_settings.vs_manager ==
|
||||
current_user) {
|
||||
syms.Add(u.SecTup.Symbol);
|
||||
syms.Add(u.SymbolName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,16 +81,14 @@ namespace mbts.spark {
|
||||
SystemContractData sc_data = _bb.read_state(SparkTags.SystemContractsTag, null);
|
||||
IReadOnlyDictionary<string, OptionTheoInterpolationData> all_theos =
|
||||
_bb.read_state(SparkTags.AllInterpGreeks, null);
|
||||
all_theos = _filter_for_publish(all_theos);
|
||||
// find the symbol vs vs_id, get the committed vs, see if it is
|
||||
// owned by the current user, and only then publish it
|
||||
IReadOnlyDictionary<string, OptionDriverPriceMap> all_drivers =
|
||||
_bb.read_state(SparkTags.AllOptionDriverBBOTag, null);
|
||||
if (sc_data == null || all_theos == null || all_drivers == null)
|
||||
return;
|
||||
_timer.start();
|
||||
all_theos = _filter_for_publish(all_theos);
|
||||
if (all_theos.Count == 0) {
|
||||
bts.Log.Gen.info($"InterpTheosServerPublisher._publish_data all_theos.Count == 0");
|
||||
return;
|
||||
}
|
||||
IDictionary<UInt32, DriverMD> driver_map = _get_drivers(all_drivers, sc_data);
|
||||
IEnumerable<Tuple<SecurityImmutable, TheoPoint>> theo_map = _get_theos(all_theos, sc_data);
|
||||
// assemble it together and send it to the server
|
||||
@@ -115,7 +111,6 @@ namespace mbts.spark {
|
||||
ptp.Vega = is_call ? tp.cvega : tp.pvega;
|
||||
ptp.Theta = is_call ? tp.c_theta : tp.p_theta;
|
||||
ptp.Rho = Double.NaN;
|
||||
ptp.Vol = tp.vol;
|
||||
ptp_list.Add(ptp);
|
||||
}
|
||||
bts.api.orderman.PrecomputedTheos server_theos = new PrecomputedTheos();
|
||||
@@ -126,7 +121,7 @@ namespace mbts.spark {
|
||||
_order_service.set_precomputed_theos(server_theos);
|
||||
_timer.stop();
|
||||
var pub_time = _timer.lastIntervalTime;
|
||||
bts.Log.Gen.info($"InterpTheosServerPublisher._publish_data symbols: {all_theos.Count} " +
|
||||
bts.Log.Gen.info($"InterpTheosServerPublisher._publish_data " +
|
||||
$"size: {server_theos.Theos.Count} comp_time: {comp_time} msecs " +
|
||||
$"pub_time: {pub_time}");
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
set(sources api/analytics/ExpirationDriver.proto;api/analytics/TimeWeightedInterpolatedDriver.proto;api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/domain/Currency.proto;api/domain/SecurityCriteria.proto;api/domain/SecurityCriteriaClause.proto;api/domain/SecurityExpiration.proto;api/domain/SecurityMetadata.proto;api/domain/SecurityMetadataCollection.proto;api/domain/SecurityMetadataItem.proto;api/domain/SecurityType.proto;api/domain/TickDisplayRule.proto;api/domain/TickDisplaySettings.proto;api/domain/TickFactors.proto;api/domain/Venue.proto;api/io/URL.proto;api/md/MarketDataSubscriptionParams.proto;api/md/binance/BinanceDepthStreamParams.proto;api/md/binance/BinanceMarketDataSubscriptionParams.proto;api/md/deribit/DeribitMarketDataSubscriptionParams.proto;api/md/ftx/FTXDepthStreamParams.proto;api/md/ftx/FTXMarketDataSubscriptionParams.proto;api/md/glbx/GlbxMarketDataSubscriptionParams.proto;api/md/huobi/HuobiMarketDataSubscriptionParams.proto;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/AnalyticsService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MarketDataService.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/SecurityMetadataCollection.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/algo_types.proto;config/protos/cme_reference_data.proto;config/protos/exchange_sim_cfg.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/market_data.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/ports.proto;config/protos/position_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spartan.proto;config/protos/spreader.proto;config/protos/subprocess.proto;config/protos/symbols.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/protos/ui.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;io/QueryParams.cpp;io/URL.cpp;io/http/CurlHandle.cpp;io/http/HTTPClient.cpp;io/http/HTTPHeaders.cpp;io/http/HTTPRequest.cpp;io/http/HTTPResponse.cpp;io/websocket/WebsocketClient.cpp;io/websocket/WebsocketClientConfiguration.cpp;io/websocket/WebsocketError.cpp;io/websocket/WebsocketMessage.cpp;io/websocket/WebsocketSSLClientInternal.cpp;io/websocket/tests/WebsocketClientTests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/CCApiDepthWalker.cpp;md/CCApiListenerAdaptor.cpp;md/CCApiRequestor.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MarketDataLine truncated
|
||||
set(sources api/analytics/ExpirationDriver.proto;api/analytics/TimeWeightedInterpolatedDriver.proto;api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/domain/Currency.proto;api/domain/SecurityCriteria.proto;api/domain/SecurityCriteriaClause.proto;api/domain/SecurityExpiration.proto;api/domain/SecurityMetadata.proto;api/domain/SecurityMetadataCollection.proto;api/domain/SecurityMetadataItem.proto;api/domain/SecurityType.proto;api/domain/TickDisplaySettings.proto;api/domain/TickFactors.proto;api/domain/Venue.proto;api/io/URL.proto;api/md/MarketDataSubscriptionParams.proto;api/md/binance/BinanceDepthStreamParams.proto;api/md/binance/BinanceMarketDataSubscriptionParams.proto;api/md/deribit/DeribitMarketDataSubscriptionParams.proto;api/md/ftx/FTXDepthStreamParams.proto;api/md/ftx/FTXMarketDataSubscriptionParams.proto;api/md/glbx/GlbxMarketDataSubscriptionParams.proto;api/md/huobi/HuobiMarketDataSubscriptionParams.proto;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/AnalyticsService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MarketDataService.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/SecurityMetadataCollection.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/algo_types.proto;config/protos/cme_reference_data.proto;config/protos/exchange_sim_cfg.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/market_data.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/ports.proto;config/protos/position_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spartan.proto;config/protos/spreader.proto;config/protos/subprocess.proto;config/protos/symbols.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/protos/ui.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;io/QueryParams.cpp;io/URL.cpp;io/http/CurlHandle.cpp;io/http/HTTPClient.cpp;io/http/HTTPHeaders.cpp;io/http/HTTPRequest.cpp;io/http/HTTPResponse.cpp;io/websocket/WebsocketClient.cpp;io/websocket/WebsocketClientConfiguration.cpp;io/websocket/WebsocketError.cpp;io/websocket/WebsocketMessage.cpp;io/websocket/WebsocketSSLClientInternal.cpp;io/websocket/tests/WebsocketClientTests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/CCApiDepthWalker.cpp;md/CCApiListenerAdaptor.cpp;md/CCApiRequestor.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MarketDataError.cpp;md/MarketDataGateway.cpLine truncated
|
||||
@@ -44,7 +44,6 @@ message PrecomputedTheoPoint {
|
||||
double vega = 60;
|
||||
double theta = 70;
|
||||
double rho = 80;
|
||||
double vol = 90;
|
||||
}
|
||||
|
||||
message PrecomputedTheos {
|
||||
|
||||
@@ -114,10 +114,6 @@ inline bool is_same(Price p1, Price p2) {
|
||||
return std::abs(p1.value() - p2.value()) < market_epsilon();
|
||||
}
|
||||
|
||||
inline bool is_same(double d1, double d2) {
|
||||
return std::abs(d1 - d2) < market_epsilon();
|
||||
}
|
||||
|
||||
inline bool is_equal_or_better(api::Side side, Price p1, Price p2) {
|
||||
return is_same(p1, p2) || is_better(side, p1, p2);
|
||||
}
|
||||
|
||||
@@ -25,9 +25,5 @@ class ITheoCalculator {
|
||||
bts::api::orderman::PrecomputedTheoPoint &result) const = 0;
|
||||
// gets the driver security for a security with id sec_id
|
||||
virtual std::optional<uint32_t> get_driver_sec(uint32_t sec_id) const = 0;
|
||||
// given a vol for an option and the current driver, returns the theo that
|
||||
// corresponds to that vol.
|
||||
virtual double get_theo_correspoding_to_vol(
|
||||
uint32_t sec_id, double driver, double vol) const = 0;
|
||||
};
|
||||
} // namespace bts::orderman::analytics
|
||||
@@ -50,15 +50,12 @@ void interpolate(
|
||||
lower.driver(), lower.theta(), higher.driver(), higher.theta(), driver);
|
||||
double rho = lin_interp_exterp(
|
||||
lower.driver(), lower.rho(), higher.driver(), higher.rho(), driver);
|
||||
double vol = lin_interp_exterp(
|
||||
lower.driver(), lower.vol(), higher.driver(), higher.vol(), driver);
|
||||
result.set_theo(theo);
|
||||
result.set_delta(delta);
|
||||
result.set_gamma(gamma);
|
||||
result.set_vega(vega);
|
||||
result.set_theta(theta);
|
||||
result.set_rho(rho);
|
||||
result.set_vol(vol);
|
||||
}
|
||||
|
||||
struct DriverNeighbors {
|
||||
@@ -216,24 +213,6 @@ std::optional<uint32_t> TheoCalculator::get_driver_sec(uint32_t sec_id) const {
|
||||
return me->total_theo_data.get_driver_sec(sec_id);
|
||||
}
|
||||
|
||||
double TheoCalculator::get_theo_correspoding_to_vol(
|
||||
uint32_t sec_id, double driver, double vol) const {
|
||||
PrecomputedTheoPoint rv;
|
||||
if (!get_theo(sec_id, driver, rv)) {
|
||||
return bts::os::nan();
|
||||
}
|
||||
// use the vega to compute the theo
|
||||
double d_vol = vol - rv.vol();
|
||||
double d_theo = rv.vega() * d_vol;
|
||||
double new_theo = rv.theo() + d_theo;
|
||||
LOG(Gen, Info,
|
||||
"TheoCalculator::get_theo_correspoding_to_vol sec_id: {} driver: {} "
|
||||
"vol: {} rv.theo: {} rv.vol: {} rv.vega: {} "
|
||||
"new_theo: {}",
|
||||
sec_id, driver, vol, rv.theo(), rv.vol(), rv.vega(), new_theo);
|
||||
return new_theo;
|
||||
}
|
||||
|
||||
void TheoCalculator::set_data(const PrecomputedTheos &theos) {
|
||||
LOG(Gen, Info, "TheoCalculator::set_data size: {}", theos.theos_size());
|
||||
WriteLock write_lock(me->lock);
|
||||
|
||||
@@ -23,8 +23,6 @@ class TheoCalculator : public ITheoCalculator {
|
||||
double driver,
|
||||
bts::api::orderman::PrecomputedTheoPoint &result) const override;
|
||||
std::optional<uint32_t> get_driver_sec(uint32_t sec_id) const override;
|
||||
double get_theo_correspoding_to_vol(
|
||||
uint32_t sec_id, double driver, double vol) const override;
|
||||
void set_data(const bts::api::orderman::PrecomputedTheos &theos);
|
||||
|
||||
private:
|
||||
|
||||
@@ -279,13 +279,5 @@ inline Quantity get_update_quantity(const bts::api::orderman::Update &u) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
inline void set_update_quantity(
|
||||
bts::api::orderman::Update &state, Quantity cqty) {
|
||||
uint32_t int_qty = cqty.int_part();
|
||||
double fractional_qty = cqty.fractional_part();
|
||||
state.set_quantity(int_qty);
|
||||
state.mutable_fractional_quantity()->set_fraction(fractional_qty);
|
||||
}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "lib/orderman/orderman_utils/orderman_utils.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/LimitCoverAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/TaskingEyeAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/VolAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/limit_cover/LimitCoverAdapter.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/tests/ExecutionTesterAlgo.h"
|
||||
#include "lib/plugin/SparkServices.h"
|
||||
@@ -326,19 +325,6 @@ extern "C" void init_task_eye_plugin(bts::SparkServices &srv) {
|
||||
});
|
||||
}
|
||||
|
||||
extern "C" void init_vol_algo_plugin(bts::SparkServices &srv) {
|
||||
DynamicOrderDescriptor vol_algo;
|
||||
vol_algo.set_dynamic_order_type("Vol");
|
||||
//*vol_algo.add_param_desc() = param_string("Account Override");
|
||||
*vol_algo.add_param_desc() = param_double("Vol");
|
||||
*vol_algo.add_param_desc() = param_bool("Cross At Entry?");
|
||||
*vol_algo.add_param_desc() = param_bool("Requote?");
|
||||
*vol_algo.add_param_desc() = param_bool("Improve Price?");
|
||||
*vol_algo.add_param_desc() = param_int32("Distance From Top");
|
||||
srv.register_dynamic_algo_order(
|
||||
vol_algo, []() { return std::make_unique<orderman::VolAlgo>(); });
|
||||
}
|
||||
|
||||
extern "C" void init_spark_plugin(bts::SparkServices &srv) {
|
||||
auto &dyn_algo_config = config::get<config::toggles::DynamicAlgos>();
|
||||
if (dyn_algo_config.enable_dorman())
|
||||
@@ -359,7 +345,6 @@ extern "C" void init_spark_plugin(bts::SparkServices &srv) {
|
||||
init_execution_tester_plugin(srv);
|
||||
// init_sniper_plugin(srv);
|
||||
init_task_eye_plugin(srv);
|
||||
init_vol_algo_plugin(srv);
|
||||
}
|
||||
|
||||
} // namespace dorman
|
||||
|
||||
@@ -1,354 +0,0 @@
|
||||
#include "VolAlgo.h"
|
||||
#include "lib/api/services/OrderService.pb.h"
|
||||
#include "lib/domain_model/Security.h"
|
||||
#include "lib/domain_model/Security.pb.h"
|
||||
#include "lib/domain_model/SecurityKey.h"
|
||||
#include "lib/domain_model/common.h"
|
||||
#include "lib/logging/logging.h"
|
||||
#include "lib/md/PriceSize.h"
|
||||
#include "lib/orderman/ChildOrder.h"
|
||||
#include "lib/orderman/OrderBuilder.h"
|
||||
#include "lib/orderman/limiter/SecurityLimitNode.h"
|
||||
#include "lib/orderman/order_factory/IOrderFactory.h"
|
||||
#include "lib/orderman/orderman_utils/Book.h"
|
||||
#include "lib/orderman/orderman_utils/orderman_common.h"
|
||||
#include "lib/orderman/orderman_utils/orderman_utils.h"
|
||||
#include "lib/orderman/orders/OrderOpResult.h"
|
||||
#include "lib/orderman/orders/algo/ChildTemplate.h"
|
||||
#include "lib/orderman/orders/algo/IAlgoOrder.h"
|
||||
#include "lib/orderman/orders/algo/IAlgoServices.h"
|
||||
#include "lib/orderman/orders/algo/IBeforeLaunchAlgoServices.h"
|
||||
#include "lib/os/os.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
#include "lib/utils/bts_assert.h"
|
||||
#include <bits/stdint-uintn.h>
|
||||
#include <google/protobuf/util/time_util.h>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
using namespace bts::api::orderman;
|
||||
|
||||
namespace bts::orderman {
|
||||
|
||||
ChildTemplate *get_vol_algo_child_template(
|
||||
IBeforeLaunchAlgoServices &serv,
|
||||
SecurityKey key,
|
||||
api::Side side,
|
||||
std::optional<std::string> account_override) {
|
||||
OrderDefinition order_def = serv.definition();
|
||||
order_def.set_security_key(key.value());
|
||||
order_def.set_side(side);
|
||||
order_def.set_time_in_force(order_def.time_in_force());
|
||||
if (account_override.has_value()) {
|
||||
// no need for it now
|
||||
}
|
||||
order_def.mutable_custom_def()->mutable_limit()->MergeFrom(
|
||||
api::orderman::LimitOrderDefinition());
|
||||
return &(serv.make_child_template(order_def));
|
||||
}
|
||||
|
||||
struct VolAlgoParams {
|
||||
std::optional<std::string> account_override;
|
||||
double vol_perc;
|
||||
bool cross_at_entry = false;
|
||||
bool requote = false;
|
||||
bool improve_price = false;
|
||||
int distance_from_top = 2;
|
||||
};
|
||||
|
||||
std::optional<VolAlgoParams> parse_parameters(
|
||||
const DynamicOrderDefinition &def) {
|
||||
const auto &d_params = def.order_params();
|
||||
VolAlgoParams rv = {};
|
||||
// vol
|
||||
auto vol_perc = get_if<double>(d_params, "Vol");
|
||||
if (!vol_perc.has_value())
|
||||
return std::nullopt;
|
||||
rv.vol_perc = vol_perc.value();
|
||||
// cross at entry
|
||||
auto cross_at_entry = get_if<bool>(d_params, "Cross At Entry?");
|
||||
rv.cross_at_entry =
|
||||
cross_at_entry.has_value() ? cross_at_entry.value() : false;
|
||||
// requote
|
||||
auto requote = get_if<bool>(d_params, "Requote?");
|
||||
rv.requote = requote.has_value() ? requote.value() : false;
|
||||
// improve price
|
||||
auto improve_price = get_if<bool>(d_params, "Improve Price?");
|
||||
rv.improve_price = improve_price.has_value() ? improve_price.value() : false;
|
||||
// Distance from Top
|
||||
auto distance_from_top = get_if<int>(d_params, "Distance From Top");
|
||||
if (!distance_from_top.has_value())
|
||||
return std::nullopt;
|
||||
rv.distance_from_top = distance_from_top.value();
|
||||
return rv;
|
||||
}
|
||||
|
||||
struct VolAlgo ::PImpl {
|
||||
IAlgoServices *service_ptr = nullptr;
|
||||
analytics::ITheoCalculator const *theo_calc = nullptr;
|
||||
OrderKey order_key;
|
||||
uint32_t sec_key;
|
||||
api::Side side;
|
||||
std::optional<std::string> account_override;
|
||||
double qty = 0;
|
||||
VolAlgoParams params = {};
|
||||
uint32_t driver_sec_key = 0;
|
||||
bool subbed_to_driver = false;
|
||||
std::optional<Book> driver_book = std::nullopt;
|
||||
std::optional<Book> sec_book = std::nullopt;
|
||||
// out
|
||||
ChildTemplate *child_order = nullptr;
|
||||
std::optional<OrderKey> child_order_key = std::nullopt;
|
||||
Price current_price = Price{os::nan()};
|
||||
bool inited() const {
|
||||
// once we have receved both books we are ready to go
|
||||
return driver_book.has_value() && sec_book.has_value();
|
||||
}
|
||||
bool order_fired() const { return child_order_key.has_value(); }
|
||||
};
|
||||
|
||||
VolAlgo::VolAlgo() : me(new PImpl()) { LOG(OrderMan, Info, "VolAlgo created"); }
|
||||
|
||||
VolAlgo::~VolAlgo() {}
|
||||
|
||||
OrderOpResult VolAlgo::do_before_launch(IBeforeLaunchAlgoServices &serv) {
|
||||
LOG(OrderMan, Info,
|
||||
"VolAlgo::do_before_launch order_key: {} security: {} "
|
||||
"definition: {}",
|
||||
serv.order_key().value(), utils::pb::to_string(serv.security()),
|
||||
utils::pb::to_string(serv.definition()));
|
||||
auto &def = serv.definition();
|
||||
me->order_key = serv.order_key();
|
||||
me->sec_key = def.security_key();
|
||||
me->side = def.side();
|
||||
if (def.has_custom_def() && def.custom_def().has_dynamic()) {
|
||||
auto va_params = parse_parameters(def.custom_def().dynamic());
|
||||
if (!va_params.has_value()) {
|
||||
return {
|
||||
bts::api::orderman::OrderError::ORDER_ERROR_INVALID_PARAMETER,
|
||||
std::string("Parameters are not well formed")};
|
||||
}
|
||||
me->params = va_params.value();
|
||||
me->child_order = get_vol_algo_child_template(
|
||||
serv, SecurityKey(me->sec_key), me->side,
|
||||
me->params.account_override);
|
||||
LOG(OrderMan, Info,
|
||||
"VolAlgo::do_before_launch order_key: {} sec_key: {} side: {} vol: "
|
||||
"{} cross_at_entry: {} re_quote: {} improve_price: {} "
|
||||
"distance_from_top: {}",
|
||||
me->order_key, me->sec_key, bts::api::Side_Name(me->side),
|
||||
me->params.vol_perc, me->params.cross_at_entry, me->params.requote,
|
||||
me->params.improve_price, me->params.distance_from_top);
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
bts::api::orderman::OrderError::ORDER_ERROR_INVALID_PARAMETER,
|
||||
std::string("Parameters are not well formed")};
|
||||
}
|
||||
|
||||
void VolAlgo::do_launch(IAlgoServices &serv) {
|
||||
LOG(OrderMan, Info, "VolAlgo::do_launch order_key: {} qty: {}",
|
||||
serv.order_key().value(), serv.quantity());
|
||||
me->service_ptr = &serv;
|
||||
me->qty = serv.quantity().full_value();
|
||||
me->service_ptr->subscribe_theos();
|
||||
me->service_ptr->subscribe_timer();
|
||||
me->service_ptr->subscribe_book(SecurityKey(me->sec_key));
|
||||
}
|
||||
|
||||
void VolAlgo::do_launch_attached(IAlgoServices &serv, OrderKey, ChildState) {
|
||||
me->service_ptr = &serv;
|
||||
_terminate_algo(true, "Vol Algo can not be attached to working orders");
|
||||
}
|
||||
|
||||
void VolAlgo::on_book(SecurityKey sec_key, Book const &book) {
|
||||
LOG(OrderMan, Diag, "VolAlgo::on_book order_key: {} sec_key: {}",
|
||||
me->order_key, sec_key);
|
||||
if (sec_key.value() == me->sec_key) {
|
||||
me->sec_book = book;
|
||||
_analyze_and_act();
|
||||
} else if (sec_key.value() == me->driver_sec_key) {
|
||||
me->driver_book = book;
|
||||
_analyze_and_act();
|
||||
}
|
||||
}
|
||||
void VolAlgo::do_update(api::orderman::Update const &u) {
|
||||
LOG(OrderMan, Info,
|
||||
"VolAlgo::do_update order_key: {} sec_key: {} "
|
||||
"update: {}",
|
||||
me->order_key, me->sec_key, utils::pb::to_string(u));
|
||||
const auto &p = u.custom().dynamic();
|
||||
auto params = parse_parameters(p);
|
||||
if (!params.has_value()) {
|
||||
LOG(Gen, Error,
|
||||
"VolAlgo::do_update order_key: {} parameters are not well formed",
|
||||
me->order_key);
|
||||
return;
|
||||
}
|
||||
me->qty = u.quantity();
|
||||
me->params = params.value();
|
||||
_analyze_and_act(true);
|
||||
// price changes are ignored the price is the vol
|
||||
}
|
||||
|
||||
void VolAlgo::on_child_change(OrderKey, ChildState const &state) {
|
||||
// price / qty is reflected from the child
|
||||
me->service_ptr->update_fill_state(state.total_fills, state.last_price);
|
||||
switch (state.status) {
|
||||
case ChildStatus::WORKING:
|
||||
break;
|
||||
case ChildStatus::COMPLETED:
|
||||
me->service_ptr->complete();
|
||||
break;
|
||||
case ChildStatus::CANCELED:
|
||||
me->service_ptr->cancel("Child Order Cancelled");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VolAlgo::on_status(SecurityKey, co2::TradingStatus) {}
|
||||
void VolAlgo::on_timer() {}
|
||||
|
||||
void VolAlgo::on_theos(analytics::ITheoCalculator const *theo_calculator) {
|
||||
LOG(OrderMan, Info, "VolAlgo::on_theos order_key: {}", me->order_key);
|
||||
me->theo_calc = theo_calculator;
|
||||
if (me->subbed_to_driver) {
|
||||
_analyze_and_act();
|
||||
return;
|
||||
}
|
||||
auto driver_sec = me->theo_calc->get_driver_sec(me->sec_key);
|
||||
if (driver_sec.has_value()) {
|
||||
LOG(OrderMan, Info,
|
||||
"VolAlgo::on_theos order_key: {} subscribing to driver sec_key: {}",
|
||||
me->order_key, driver_sec.value());
|
||||
me->subbed_to_driver = true;
|
||||
me->driver_sec_key = driver_sec.value();
|
||||
me->service_ptr->subscribe_book(SecurityKey(me->driver_sec_key));
|
||||
} else {
|
||||
LOG(OrderMan, Warn,
|
||||
"VolAlgo::on_theos order_key: {} could not find driver",
|
||||
me->order_key);
|
||||
}
|
||||
}
|
||||
void VolAlgo::on_position(PositionUpdate const &) {}
|
||||
|
||||
// this is where all the action happens, both new order (just once) as well as
|
||||
// order updates
|
||||
void VolAlgo::_analyze_and_act(bool force_reprice) {
|
||||
// check for period (to stop frequent updates)
|
||||
auto get_driver = [&]() {
|
||||
const md::PriceSize &driver_bid = me->driver_book->bid().at(0);
|
||||
const md::PriceSize &driver_ask = me->driver_book->ask().at(0);
|
||||
if (bts::securities::is_same(driver_bid.size(), 0) ||
|
||||
bts::securities::is_same(driver_ask.size(), 0))
|
||||
return os::nan();
|
||||
// finding weighted mean (TODO change it to mark price later)
|
||||
double driver = (driver_bid.price() * driver_bid.size() +
|
||||
driver_ask.price() * driver_ask.size()) /
|
||||
(driver_bid.size() + driver_ask.size());
|
||||
return driver;
|
||||
};
|
||||
auto crosses_opp_market = [&](Price order_price) {
|
||||
if (me->side == api::SIDE_BUY) {
|
||||
double top = me->sec_book->ask().at(0).price();
|
||||
return securities::gr_than_eq(order_price.value(), top);
|
||||
} else {
|
||||
double top = me->sec_book->bid().at(0).price();
|
||||
return securities::gr_than_eq(top, order_price.value());
|
||||
}
|
||||
};
|
||||
if (me->order_fired()) {
|
||||
// repricing if parameters (and arg) allows
|
||||
if (!me->params.requote && !force_reprice)
|
||||
return;
|
||||
// working order
|
||||
double driver = get_driver();
|
||||
if (os::is_nan(driver)) {
|
||||
// keep working it
|
||||
return;
|
||||
}
|
||||
double theo_unnorm = me->theo_calc->get_theo_correspoding_to_vol(
|
||||
me->sec_key, driver, me->params.vol_perc / 100.0);
|
||||
// TODO: normalize
|
||||
double theo = theo_unnorm / driver;
|
||||
Price new_price = _get_order_price(theo);
|
||||
LOG(OrderMan, Info,
|
||||
"VolAlgo::_analyze_and_act (calc updating) order_key: {} "
|
||||
"theo_unnorm: {} driver: {} theo: {} order_price: {}",
|
||||
me->order_key, theo_unnorm, driver, theo, new_price);
|
||||
if (securities::is_same(me->current_price, new_price)) {
|
||||
return;
|
||||
}
|
||||
bool improving =
|
||||
securities::is_better(me->side, new_price, me->current_price);
|
||||
if (!improving || me->params.improve_price || force_reprice) {
|
||||
bts::api::orderman::Update update;
|
||||
update.set_price(new_price.value());
|
||||
set_update_quantity(update, Quantity::create_new(me->qty));
|
||||
me->current_price = new_price;
|
||||
LOG(Gen, Info,
|
||||
"VolAlgo::_analyze_and_act updating order order_key: {} price: {} "
|
||||
"qty: {}",
|
||||
me->order_key, me->current_price, me->qty);
|
||||
me->service_ptr->update_child(me->child_order_key.value(), update);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// new order path
|
||||
if (me->inited()) {
|
||||
// time to fire
|
||||
double driver = get_driver();
|
||||
if (os::is_nan(driver)) {
|
||||
return;
|
||||
}
|
||||
// entering order
|
||||
double theo_unnorm = me->theo_calc->get_theo_correspoding_to_vol(
|
||||
me->sec_key, driver, me->params.vol_perc / 100.0);
|
||||
double theo = theo_unnorm / driver;
|
||||
Price order_price = _get_order_price(theo);
|
||||
LOG(OrderMan, Info,
|
||||
"VolAlgo::_analyze_and_act (calc new) order_key: {} theo_unnorm: "
|
||||
"{} driver: {} theo: {} order_price: {}",
|
||||
me->order_key, theo_unnorm, driver, theo, order_price);
|
||||
if (!me->params.cross_at_entry && crosses_opp_market(order_price))
|
||||
return;
|
||||
me->current_price = order_price;
|
||||
LOG(Gen, Info,
|
||||
"VolAlgo::_analyze_and_act placing order order_key: {} price: {} "
|
||||
"qty: {}",
|
||||
me->order_key, me->current_price, me->qty);
|
||||
me->child_order_key = me->service_ptr->launch_child(
|
||||
*me->child_order, me->current_price,
|
||||
Quantity::create_new(me->qty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VolAlgo::_terminate_algo(bool is_error, const std::string &err_msg) {
|
||||
// TODO unsub ?
|
||||
if (is_error) {
|
||||
me->service_ptr->terminate_error(err_msg);
|
||||
} else {
|
||||
me->service_ptr->complete();
|
||||
}
|
||||
}
|
||||
|
||||
Price VolAlgo::_get_order_price(double theo) const {
|
||||
// BTC Opts (p <= 0.005) : price = 0.0001 qty = 0.1
|
||||
// BTC Opts (p > 0.005) : price = 0.0005 qty = 0.1
|
||||
// -------------------------------------------------
|
||||
// ETH Opts (p <= 0.005) : price = 0.0001 qty = 1
|
||||
// ETH Opts (p > 0.005) : price = 0.0005 qty = 1
|
||||
// TODO: get the above from the security itself
|
||||
double rv = 0;
|
||||
if (theo > 0.005) {
|
||||
rv = securities::raw_round_to_quote_price(theo, 0.0005, me->side);
|
||||
} else {
|
||||
rv = securities::raw_round_to_quote_price(theo, 0.0001, me->side);
|
||||
}
|
||||
LOG(Gen, Info,
|
||||
"VolAlgo::_get_order_price order_key: {} theo: {} order_price: {}",
|
||||
me->order_key, theo, rv);
|
||||
return Price{rv};
|
||||
}
|
||||
} // namespace bts::orderman
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/domain_model/SecurityKey.h"
|
||||
#include "lib/domain_model/common.h"
|
||||
#include "lib/orderman/calculations/ITheoCalculator.h"
|
||||
#include "lib/orderman/orders/algo/IAlgoOrder.h"
|
||||
#include <openssl/ossl_typ.h>
|
||||
|
||||
namespace bts::orderman {
|
||||
|
||||
// This is a test algo, not to be used in prod, that sends an order and modifies
|
||||
// it by moving the price up and down at a given period
|
||||
class VolAlgo : public IAlgoOrder {
|
||||
public:
|
||||
VolAlgo();
|
||||
~VolAlgo();
|
||||
OrderOpResult do_before_launch(IBeforeLaunchAlgoServices &) override;
|
||||
void on_book(SecurityKey, Book const &) override;
|
||||
void do_launch(IAlgoServices &) override;
|
||||
void do_launch_attached(IAlgoServices &, OrderKey, ChildState) override;
|
||||
void do_update(api::orderman::Update const &) override;
|
||||
void on_child_change(OrderKey, ChildState const &) override;
|
||||
void on_status(SecurityKey, co2::TradingStatus) override;
|
||||
void on_timer() override;
|
||||
void on_theos(analytics::ITheoCalculator const *theo_calculator) override;
|
||||
void on_position(PositionUpdate const &) override;
|
||||
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
|
||||
private:
|
||||
void _analyze_and_act(bool force_reprice = false);
|
||||
void _terminate_algo(bool is_error, const std::string &err_msg);
|
||||
Price _get_order_price(double theo) const;
|
||||
};
|
||||
|
||||
} // namespace bts::orderman
|
||||
@@ -8,18 +8,17 @@ if exist %venv_dir% (
|
||||
echo Removing python virtual environment
|
||||
rmdir /S /Q %venv_dir%
|
||||
) else (
|
||||
GOTO END
|
||||
GOTO ERROR
|
||||
)
|
||||
)
|
||||
|
||||
echo Creating python virtual environment
|
||||
@call python -m venv %venv_dir%
|
||||
@call %venv_dir%\Scripts\activate.bat
|
||||
@call %venv_dir%\Scripts\python -m pip install --upgrade pip
|
||||
@call pip install --upgrade pip
|
||||
@call %venv_dir%\Scripts\pip install -r %~dp0..\requirements.txt
|
||||
@call deactivate
|
||||
|
||||
:END
|
||||
EXIT /B %ERRORLEVEL%
|
||||
|
||||
:ERROR
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
@echo off
|
||||
|
||||
call "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\Tools\\VsDevCmd.bat"
|
||||
call .venv\\Scripts\\activate
|
||||
call set PYTHONPATH=%~dp0\..\.venv\Scripts\python
|
||||
call .venv\Scripts\python.exe tools\py\build_spark.py %*
|
||||
|
||||
EXIT /B %ERRORLEVEL%
|
||||
@@ -173,7 +173,8 @@ def _get_arg_parser():
|
||||
metavar='debug|release',
|
||||
type=str,
|
||||
nargs='?',
|
||||
help='The build configuration')
|
||||
help='The build configuration',
|
||||
default='Debug')
|
||||
|
||||
parser.add_argument(
|
||||
'-o',
|
||||
@@ -335,10 +336,9 @@ def _main():
|
||||
link_build_dir = arg_to_path(get_arg(args_dict, 'link_output_dir'))
|
||||
targets = flatten_arglist(get_arg(args_dict, 'target'))
|
||||
verbosity = get_arg(args_dict, 'verbosity') or None
|
||||
configuration = args.configuration or 'Release' if targets is not None and any(
|
||||
filter(lambda t: t.lower() == 'publish', targets)) else 'Debug'
|
||||
|
||||
build(
|
||||
configuration=configuration,
|
||||
configuration=args.configuration,
|
||||
clean=args.clean,
|
||||
restore=args.restore,
|
||||
build_dir=build_dir,
|
||||
|
||||
Reference in new issue
Block a user