Skip to content

Commit c7edf17

Browse files
authored
Refactored sweep code out of load, and added some tests (#48)
1 parent 0b05da3 commit c7edf17

11 files changed

Lines changed: 464 additions & 67 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ target_include_directories(BacktestingEngineLib PUBLIC
5656
${CMAKE_SOURCE_DIR}/include/trading
5757
${CMAKE_SOURCE_DIR}/include/trading_definitions
5858
${CMAKE_SOURCE_DIR}/include/strategies
59+
${CMAKE_SOURCE_DIR}/include/sweep
5960
${CMAKE_SOURCE_DIR}/external
6061
)
6162

backtesting-engine-cpp.xcodeproj/project.pbxproj

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
940F6E532FD9479800B0364A /* randomStrategySweep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E502FD9479800B0364A /* randomStrategySweep.cpp */; };
11+
940F6E542FD9479800B0364A /* runConfigurationBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E512FD9479800B0364A /* runConfigurationBuilder.cpp */; };
12+
940F6E552FD9479800B0364A /* randomStrategySweep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E502FD9479800B0364A /* randomStrategySweep.cpp */; };
13+
940F6E562FD9479800B0364A /* runConfigurationBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E512FD9479800B0364A /* runConfigurationBuilder.cpp */; };
14+
940F6E582FD947A900B0364A /* decimalConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E572FD947A900B0364A /* decimalConvert.cpp */; };
15+
940F6E592FD947A900B0364A /* decimalConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E572FD947A900B0364A /* decimalConvert.cpp */; };
16+
940F6E5B2FD947C000B0364A /* sweep.mm in Sources */ = {isa = PBXBuildFile; fileRef = 940F6E5A2FD947B800B0364A /* sweep.mm */; };
1017
941408AE2D59F93F000ED1F9 /* sqlManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941408AD2D59F93F000ED1F9 /* sqlManager.cpp */; };
1118
941408AF2D59F93F000ED1F9 /* sqlManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941408AD2D59F93F000ED1F9 /* sqlManager.cpp */; };
1219
941B549A2D3BBADE00E3BF64 /* trading_definitions_json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941B54992D3BBADD00E3BF64 /* trading_definitions_json.cpp */; };
@@ -69,6 +76,13 @@
6976

7077
/* Begin PBXFileReference section */
7178
9409A61B2FAA6411002C30FF /* strategy.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = strategy.hpp; sourceTree = "<group>"; };
79+
940F6E4C2FD9477E00B0364A /* randomStrategySweep.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = randomStrategySweep.hpp; sourceTree = "<group>"; };
80+
940F6E4D2FD9477E00B0364A /* runConfigurationBuilder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = runConfigurationBuilder.hpp; sourceTree = "<group>"; };
81+
940F6E4F2FD9478800B0364A /* decimalConvert.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = decimalConvert.hpp; sourceTree = "<group>"; };
82+
940F6E502FD9479800B0364A /* randomStrategySweep.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = randomStrategySweep.cpp; sourceTree = "<group>"; };
83+
940F6E512FD9479800B0364A /* runConfigurationBuilder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = runConfigurationBuilder.cpp; sourceTree = "<group>"; };
84+
940F6E572FD947A900B0364A /* decimalConvert.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = decimalConvert.cpp; sourceTree = "<group>"; };
85+
940F6E5A2FD947B800B0364A /* sweep.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = sweep.mm; sourceTree = "<group>"; };
7286
941408AD2D59F93F000ED1F9 /* sqlManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = sqlManager.cpp; sourceTree = "<group>"; };
7387
941408B02D59F954000ED1F9 /* sqlManager.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = sqlManager.hpp; sourceTree = "<group>"; };
7488
941B54902D3BBA4900E3BF64 /* ohlc_variables.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ohlc_variables.hpp; sourceTree = "<group>"; };
@@ -1323,6 +1337,24 @@
13231337
/* End PBXFrameworksBuildPhase section */
13241338

13251339
/* Begin PBXGroup section */
1340+
940F6E4E2FD9477E00B0364A /* sweep */ = {
1341+
isa = PBXGroup;
1342+
children = (
1343+
940F6E4C2FD9477E00B0364A /* randomStrategySweep.hpp */,
1344+
940F6E4D2FD9477E00B0364A /* runConfigurationBuilder.hpp */,
1345+
);
1346+
path = sweep;
1347+
sourceTree = "<group>";
1348+
};
1349+
940F6E522FD9479800B0364A /* sweep */ = {
1350+
isa = PBXGroup;
1351+
children = (
1352+
940F6E502FD9479800B0364A /* randomStrategySweep.cpp */,
1353+
940F6E512FD9479800B0364A /* runConfigurationBuilder.cpp */,
1354+
);
1355+
path = sweep;
1356+
sourceTree = "<group>";
1357+
};
13261358
941B548F2D3BBA3B00E3BF64 /* trading_definitions */ = {
13271359
isa = PBXGroup;
13281360
children = (
@@ -1348,6 +1380,7 @@
13481380
94280BA72D2FC29F00F1CF56 /* utilities */ = {
13491381
isa = PBXGroup;
13501382
children = (
1383+
940F6E572FD947A900B0364A /* decimalConvert.cpp */,
13511384
94829FC42FCC1D1A00710E6E /* env.cpp */,
13521385
942EC5612FBEF94700CCBB5D /* redisConnection.cpp */,
13531386
94280BA22D2FC00200F1CF56 /* base64.cpp */,
@@ -1459,7 +1492,7 @@
14591492
9470B5A22C8C5AD0007D9CC6 /* source */ = {
14601493
isa = PBXGroup;
14611494
children = (
1462-
943770442FD4396F00317424 /* boostRedisImpl.cpp */,
1495+
940F6E522FD9479800B0364A /* sweep */,
14631496
9437703E2FD42FC000317424 /* reporting */,
14641497
941B54982D3BBAD800E3BF64 /* trading_definitions */,
14651498
94674B862D533B4000973137 /* trading */,
@@ -1468,6 +1501,7 @@
14681501
94D3A7252FC1B3AD00EBEA32 /* commands */,
14691502
94280BA72D2FC29F00F1CF56 /* utilities */,
14701503
942EC5642FBEF95000CCBB5D /* backtestRunner.cpp */,
1504+
943770442FD4396F00317424 /* boostRedisImpl.cpp */,
14711505
942EC5652FBEF95000CCBB5D /* redisLoader.cpp */,
14721506
942FDDDF2FC5C8B20096F318 /* tradingResults.cpp */,
14731507
942EC5662FBEF95000CCBB5D /* redisRunner.cpp */,
@@ -1482,6 +1516,7 @@
14821516
9470B5AD2C8C5B99007D9CC6 /* tests */ = {
14831517
isa = PBXGroup;
14841518
children = (
1519+
940F6E5A2FD947B800B0364A /* sweep.mm */,
14851520
9464E5F02FA7467200D82BAD /* symbolScale.mm */,
14861521
943398262D57E54000287A2D /* jsonParser.mm */,
14871522
94674B892D533BDA00973137 /* tradeManager.mm */,
@@ -1493,6 +1528,7 @@
14931528
94B8C7932D3D770800E17EB6 /* utilities */ = {
14941529
isa = PBXGroup;
14951530
children = (
1531+
940F6E4F2FD9478800B0364A /* decimalConvert.hpp */,
14961532
94B4F02A2FD618B300B08FB4 /* backtestLog.hpp */,
14971533
94B4F02B2FD618B300B08FB4 /* threadPool.hpp */,
14981534
945F475C2FD5607E00D19164 /* queueKeys.hpp */,
@@ -3616,6 +3652,7 @@
36163652
94DE4F772C8C3E7C00FE48FF /* include */ = {
36173653
isa = PBXGroup;
36183654
children = (
3655+
940F6E4E2FD9477E00B0364A /* sweep */,
36193656
943770422FD42FDD00317424 /* reporting */,
36203657
94D3A7232FC1B3A600EBEA32 /* commands */,
36213658
942966D72D48E84100532862 /* models */,
@@ -3740,9 +3777,12 @@
37403777
942EC56B2FBEF95000CCBB5D /* redisLoader.cpp in Sources */,
37413778
94829FC52FCC1D1A00710E6E /* env.cpp in Sources */,
37423779
942EC56C2FBEF95000CCBB5D /* redisRunner.cpp in Sources */,
3780+
940F6E592FD947A900B0364A /* decimalConvert.cpp in Sources */,
37433781
94280BA32D2FC00200F1CF56 /* base64.cpp in Sources */,
37443782
943770402FD42FC000317424 /* elasticClient.cpp in Sources */,
37453783
941B549B2D3BBADE00E3BF64 /* trading_definitions_json.cpp in Sources */,
3784+
940F6E532FD9479800B0364A /* randomStrategySweep.cpp in Sources */,
3785+
940F6E542FD9479800B0364A /* runConfigurationBuilder.cpp in Sources */,
37463786
946EFF7E2FB9F44E008D9647 /* reporting.cpp in Sources */,
37473787
94674B872D533B4000973137 /* tradeManager.cpp in Sources */,
37483788
94CD8BA02D2E8CE500041BBA /* databaseConnection.cpp in Sources */,
@@ -3779,6 +3819,10 @@
37793819
942FDDE22FC5C8B20096F318 /* tradingResults.cpp in Sources */,
37803820
9437703F2FD42FC000317424 /* elasticClient.cpp in Sources */,
37813821
9470B5B62C8C5BFD007D9CC6 /* main.cpp in Sources */,
3822+
940F6E552FD9479800B0364A /* randomStrategySweep.cpp in Sources */,
3823+
940F6E5B2FD947C000B0364A /* sweep.mm in Sources */,
3824+
940F6E562FD9479800B0364A /* runConfigurationBuilder.cpp in Sources */,
3825+
940F6E582FD947A900B0364A /* decimalConvert.cpp in Sources */,
37823826
94364CB62D416D8D00F35B55 /* db.mm in Sources */,
37833827
);
37843828
runOnlyForDeploymentPostprocessing = 0;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Backtesting Engine in C++
2+
//
3+
// (c) 2026 Ryan McCaffery | https://mccaffers.com
4+
// This code is licensed under MIT license (see LICENSE.txt for details)
5+
// ---------------------------------------
6+
7+
#pragma once
8+
9+
#include "parameterSweep.hpp"
10+
11+
namespace sweep {
12+
13+
// Declares which parameters to sweep for the RandomStrategy. Keeping the ranges
14+
// in one place means a new strategy (or extra swept parameter) is a localised
15+
// edit: register it here, then read it back in makeStrategy().
16+
ParameterGenerator buildRandomStrategySweep();
17+
18+
} // namespace sweep
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Backtesting Engine in C++
2+
//
3+
// (c) 2026 Ryan McCaffery | https://mccaffers.com
4+
// This code is licensed under MIT license (see LICENSE.txt for details)
5+
// ---------------------------------------
6+
7+
#pragma once
8+
9+
#include <string>
10+
11+
#include "run_configuration.hpp"
12+
13+
namespace sweep {
14+
15+
// The run-level descriptor: what tick data to pull from QuestDB, plus the risk
16+
// limits every strategy in the sweep runs under. Shared by every strategy in
17+
// this sweep and linked to them by RUN_ID.
18+
trading_definitions::RunConfiguration makeRunConfiguration(const std::string& runId);
19+
20+
} // namespace sweep
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Backtesting Engine in C++
2+
//
3+
// (c) 2026 Ryan McCaffery | https://mccaffers.com
4+
// This code is licensed under MIT license (see LICENSE.txt for details)
5+
// ---------------------------------------
6+
7+
#pragma once
8+
9+
#include <boost/decimal.hpp>
10+
11+
namespace decimal_convert {
12+
13+
// Converts a double into a decimal64_t via its shortest round-trip decimal
14+
// string. Routing through text (rather than constructing from the binary double)
15+
// stops clean decimals like 1.5 / 2.0 from snapping to an IEEE-754 neighbour,
16+
// consistent with how decimal_json.hpp moves values through JSON. Feed it
17+
// binary-exact values (halves, quarters) or explicit lists to keep this exact.
18+
boost::decimal::decimal64_t toDecimal(double value);
19+
20+
} // namespace decimal_convert

scripts/generate_clangd.sh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/bin/bash
2+
# Generates the .clangd IntelliSense config at the repo root.
3+
#
4+
# .clangd needs absolute, machine-specific paths (clangd resolves relative -I
5+
# flags against the inferred command's working directory, not the repo root),
6+
# so the file is gitignored and each user regenerates it locally with this
7+
# script. Re-run it after adding a new include/ subdirectory — and add the new
8+
# directory to the list below, mirroring CMakeLists.txt.
9+
10+
# Fail fast: -e exits on any error, -u errors on undefined vars,
11+
# pipefail propagates failures through pipes.
12+
set -euo pipefail
13+
14+
# Resolve paths relative to this script, not the caller's working directory,
15+
# so the script works no matter where it's invoked from.
16+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
18+
19+
# Homebrew lives at /opt/homebrew on Apple Silicon and /usr/local on Intel;
20+
# `brew --prefix` resolves the right one. The keg-only formulas (libomp,
21+
# libpq) are addressed via their own prefixes rather than <prefix>/opt/... so
22+
# the script also works if they were installed elsewhere.
23+
BREW_PREFIX="$(brew --prefix)"
24+
LIBOMP_PREFIX="$(brew --prefix libomp)"
25+
LIBPQ_PREFIX="$(brew --prefix libpq)"
26+
27+
# Where the XCTest framework lives for the active Xcode installation.
28+
XCODE_FRAMEWORKS="$(xcode-select -p)/Platforms/MacOSX.platform/Developer/Library/Frameworks"
29+
30+
OUTPUT="$REPO_ROOT/.clangd"
31+
32+
cat > "$OUTPUT" <<EOF
33+
# clangd IntelliSense config — generated by scripts/generate_clangd.sh; edit
34+
# that script (not this file) and re-run it.
35+
# The XCTest tests (tests/*.mm) are built by Xcode, not CMake, so they have no
36+
# entry in build/compile_commands.json. Without flags, clangd can't find the
37+
# XCTest framework or project headers. These flags mirror what CMake emits in
38+
# build/compile_commands.json, scoped to the .mm test files.
39+
#
40+
# NOTE: paths must be absolute. clangd resolves a relative -I against the
41+
# inferred command's working directory (build/external/libpqxx/src), not the
42+
# repo root, so relative paths break header resolution. This file is therefore
43+
# machine-specific and gitignored.
44+
If:
45+
PathMatch: .*\.mm
46+
CompileFlags:
47+
Add:
48+
- -xobjective-c++
49+
- -std=gnu++2b
50+
- -F$XCODE_FRAMEWORKS
51+
# Project headers (include/ and its subdirs — tests use bare #import "x.hpp")
52+
- -I$REPO_ROOT/include
53+
- -I$REPO_ROOT/include/commands
54+
- -I$REPO_ROOT/include/models
55+
- -I$REPO_ROOT/include/reporting
56+
- -I$REPO_ROOT/include/strategies
57+
- -I$REPO_ROOT/include/sweep
58+
- -I$REPO_ROOT/include/trading
59+
- -I$REPO_ROOT/include/trading_definitions
60+
- -I$REPO_ROOT/include/utilities
61+
# Third-party headers
62+
- -I$REPO_ROOT/external
63+
- -I$REPO_ROOT/external/boost-decimal/include
64+
- -I$REPO_ROOT/external/libpqxx/include
65+
- -I$REPO_ROOT/build/external/libpqxx/include
66+
- -I$LIBOMP_PREFIX/include
67+
- -isystem$BREW_PREFIX/include
68+
- -isystem$LIBPQ_PREFIX/include
69+
- -isystem$LIBPQ_PREFIX/include/postgresql/server
70+
EOF
71+
72+
echo "Wrote $OUTPUT"

source/commands/loadCommand.cpp

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,90 +6,31 @@
66

77
#include "loadCommand.hpp"
88

9-
#include <array>
10-
#include <charconv>
119
#include <print>
1210
#include <ranges>
13-
#include <stdexcept>
1411
#include <string>
15-
#include <system_error>
1612
#include <vector>
1713

1814
#include <boost/decimal.hpp>
19-
#include <boost/decimal/charconv.hpp>
2015
#include <boost/decimal/literals.hpp>
2116
#include <nlohmann/json.hpp>
2217

2318
#include <boost/uuid/random_generator.hpp>
2419
#include <boost/uuid/uuid_io.hpp>
2520

21+
#include "decimalConvert.hpp"
2622
#include "env.hpp"
2723
#include "parameterSweep.hpp"
2824
#include "queueKeys.hpp"
25+
#include "randomStrategySweep.hpp"
2926
#include "redisLoader.hpp"
30-
#include "run_configuration.hpp"
27+
#include "runConfigurationBuilder.hpp"
3128
#include "trading_definitions/strategy.hpp"
3229

3330
namespace {
3431

35-
using trading_definitions::RunConfiguration;
3632
using trading_definitions::Strategy;
3733

38-
// Converts a swept double into a decimal64_t via its shortest round-trip decimal
39-
// string. Routing through text (rather than constructing from the binary double)
40-
// stops clean decimals like 1.5 / 2.0 from snapping to an IEEE-754 neighbour,
41-
// consistent with how decimal_json.hpp moves values through JSON. Sweep with
42-
// binary-exact steps (halves, quarters) or explicit lists to keep this exact.
43-
boost::decimal::decimal64_t toDecimal(double value) {
44-
std::array<char, 64> buffer;
45-
const auto [ptr, ec] =
46-
std::to_chars(buffer.data(), buffer.data() + buffer.size(), value);
47-
if (ec != std::errc{}) {
48-
throw std::runtime_error("loadCommand: to_chars failed for swept decimal");
49-
}
50-
boost::decimal::decimal64_t result;
51-
const auto parsed = boost::decimal::from_chars(buffer.data(), ptr, result);
52-
if (parsed.ec != std::errc{}) {
53-
throw std::runtime_error("loadCommand: from_chars failed for swept decimal");
54-
}
55-
return result;
56-
}
57-
58-
// Declares which parameters to sweep for the RandomStrategy. Keeping the ranges
59-
// in one place means a new strategy (or extra swept parameter) is a localised
60-
// edit: register it here, then read it back in makeConfiguration().
61-
sweep::ParameterGenerator buildRandomStrategySweep() {
62-
sweep::ParameterGenerator generator;
63-
// generator.addRange("OHLC_COUNT", 80, 20, 140); // 80, 100, 120, 140
64-
// generator.addList("OHLC_MINUTES", {1, 3, 5, 8});
65-
generator.addList("STOP_DISTANCE_IN_PIPS", {1.0, 1.5, 10.0});
66-
generator.addList("LIMIT_DISTANCE_IN_PIPS", {1.0, 1.5, 10.0});
67-
return generator;
68-
}
69-
70-
// The run-level descriptor: what tick data to pull from QuestDB, plus the risk
71-
// limits every strategy in the sweep runs under. Shared by every strategy in
72-
// this sweep and linked to them by RUN_ID.
73-
RunConfiguration makeRunConfiguration(const std::string& runId) {
74-
using namespace boost::decimal::literals;
75-
return RunConfiguration{
76-
.RUN_ID = runId,
77-
.SYMBOLS = "EURUSD",
78-
.LAST_MONTHS = 6,
79-
.STARTING_BALANCE = trading_definitions::DEFAULT_STARTING_BALANCE,
80-
// Cut a run off once it has lost 5% of the account (fail fast);
81-
// set <= 0 to run without any loss cutoff.
82-
.MAX_LOSS_PERCENT = 5_DD,
83-
// Cap on simultaneously open positions per run (<= 0 = unlimited).
84-
// The per-symbol gate already limits to one trade per symbol, so this
85-
// only bites on multi-symbol runs.
86-
.MAX_OPEN_TRADES = 10,
87-
// Flip to false to silence liquidated runs from Elasticsearch once
88-
// sweeps scale up and loss-limit cutoffs are expected noise.
89-
.REPORT_FAILURES = true,
90-
};
91-
}
92-
9334
// Maps one point in the parameter grid onto a Strategy. Fields not being swept
9435
// keep their fixed defaults; swept fields are pulled from `combo`.
9536
Strategy makeStrategy(const sweep::Combination& combo) {
@@ -102,8 +43,10 @@ Strategy makeStrategy(const sweep::Combination& combo) {
10243
.UUID = boost::uuids::to_string(boost::uuids::random_generator()()),
10344
.TRADING_VARIABLES = TradingVariables{
10445
.STRATEGY = "RandomStrategy",
105-
.STOP_DISTANCE_IN_PIPS = toDecimal(combo.get("STOP_DISTANCE_IN_PIPS")),
106-
.LIMIT_DISTANCE_IN_PIPS = toDecimal(combo.get("LIMIT_DISTANCE_IN_PIPS")),
46+
.STOP_DISTANCE_IN_PIPS =
47+
decimal_convert::toDecimal(combo.get("STOP_DISTANCE_IN_PIPS")),
48+
.LIMIT_DISTANCE_IN_PIPS =
49+
decimal_convert::toDecimal(combo.get("LIMIT_DISTANCE_IN_PIPS")),
10750
.TRADING_SIZE = 1_DD,
10851
},
10952
.OHLC_VARIABLES = {
@@ -129,7 +72,7 @@ int LoadCommand::run() {
12972
const auto redisHost = env::getOr("REDIS_HOST", "127.0.0.1");
13073

13174
// Build random here
132-
const auto generator = buildRandomStrategySweep();
75+
const auto generator = sweep::buildRandomStrategySweep();
13376

13477
const auto combinations = generator.generateAllCombinations();
13578

@@ -159,7 +102,7 @@ int LoadCommand::run() {
159102
// Now advertise the run so workers can pick it up. runJson is pinned to
160103
// nlohmann::json (not auto) because makeRunConfiguration returns a
161104
// RunConfiguration and relies on the implicit conversion for .dump().
162-
const nlohmann::json runJson = makeRunConfiguration(runId);
105+
const nlohmann::json runJson = sweep::makeRunConfiguration(runId);
163106
return RedisLoader::loadPayload(redisHost, 6379, queue_keys::RUN,
164107
runJson.dump());
165108
}

0 commit comments

Comments
 (0)