Skip to content

Commit 40bca61

Browse files
authored
Read LongBridge current reserve from environment variables
1 parent 74ee42f commit 40bca61

2 files changed

Lines changed: 166 additions & 1 deletion

File tree

tests/strategy_switch_worker_validation.mjs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,165 @@ try {
670670
globalThis.fetch = originalFetch;
671671
}
672672

673+
globalThis.fetch = async (url) => {
674+
const requestUrl = String(url);
675+
if (requestUrl.includes("/LongBridgePlatform/actions/variables/CLOUD_RUN_SERVICE_TARGETS_JSON")) {
676+
return new Response(JSON.stringify({
677+
value: JSON.stringify({
678+
targets: [
679+
{
680+
service: "longbridge-quant-sg-service",
681+
strategy_profile: "mega_cap_leader_rotation_top50_balanced",
682+
runtime_target: {
683+
platform_id: "longbridge",
684+
strategy_profile: "mega_cap_leader_rotation_top50_balanced",
685+
account_scope: "SG",
686+
service_name: "longbridge-quant-sg-service",
687+
execution_mode: "live",
688+
},
689+
},
690+
],
691+
}),
692+
}), { status: 200, headers: { "Content-Type": "application/json" } });
693+
}
694+
if (requestUrl.includes("/LongBridgePlatform/environments/longbridge-sg/variables/RUNTIME_TARGET_JSON")) {
695+
return new Response(JSON.stringify({
696+
value: JSON.stringify({
697+
platform_id: "longbridge",
698+
strategy_profile: "tqqq_growth_income",
699+
dry_run_only: false,
700+
account_scope: "SG",
701+
service_name: "longbridge-quant-sg-service",
702+
execution_mode: "live",
703+
}),
704+
}), { status: 200, headers: { "Content-Type": "application/json" } });
705+
}
706+
if (requestUrl.includes("/LongBridgePlatform/environments/longbridge-sg/variables/LONGBRIDGE_MIN_RESERVED_CASH_USD")) {
707+
return new Response(JSON.stringify({ value: "25" }), {
708+
status: 200,
709+
headers: { "Content-Type": "application/json" },
710+
});
711+
}
712+
if (requestUrl.includes("/LongBridgePlatform/environments/longbridge-sg/variables/LONGBRIDGE_RESERVED_CASH_RATIO")) {
713+
return new Response(JSON.stringify({ value: "0.04" }), {
714+
status: 200,
715+
headers: { "Content-Type": "application/json" },
716+
});
717+
}
718+
if (requestUrl.includes("/InteractiveBrokersPlatform/actions/variables/CLOUD_RUN_SERVICE_TARGETS_JSON")) {
719+
return new Response(JSON.stringify({
720+
value: JSON.stringify({
721+
targets: [
722+
{
723+
service: "interactive-brokers-demo-ibkr-tqqq-service",
724+
ACCOUNT_GROUP: "demo-ibkr-tqqq",
725+
IBKR_MIN_RESERVED_CASH_USD: "150",
726+
IBKR_RESERVED_CASH_RATIO: "0.03",
727+
runtime_target: {
728+
platform_id: "ibkr",
729+
strategy_profile: "tqqq_growth_income",
730+
dry_run_only: false,
731+
account_scope: "demo-ibkr-tqqq",
732+
service_name: "interactive-brokers-demo-ibkr-tqqq-service",
733+
execution_mode: "live",
734+
},
735+
},
736+
],
737+
}),
738+
}), { status: 200, headers: { "Content-Type": "application/json" } });
739+
}
740+
if (requestUrl.includes("/CharlesSchwabPlatform/actions/variables/RUNTIME_TARGET_JSON")) {
741+
return new Response(JSON.stringify({
742+
value: JSON.stringify({
743+
platform_id: "schwab",
744+
strategy_profile: "soxl_soxx_trend_income",
745+
dry_run_only: false,
746+
account_scope: "default",
747+
service_name: "charles-schwab-quant-service",
748+
execution_mode: "live",
749+
}),
750+
}), { status: 200, headers: { "Content-Type": "application/json" } });
751+
}
752+
if (requestUrl.includes("/CharlesSchwabPlatform/actions/variables/SCHWAB_MIN_RESERVED_CASH_USD")) {
753+
return new Response(JSON.stringify({ value: "150" }), {
754+
status: 200,
755+
headers: { "Content-Type": "application/json" },
756+
});
757+
}
758+
if (requestUrl.includes("/CharlesSchwabPlatform/actions/variables/SCHWAB_RESERVED_CASH_RATIO")) {
759+
return new Response(JSON.stringify({ value: "0.03" }), {
760+
status: 200,
761+
headers: { "Content-Type": "application/json" },
762+
});
763+
}
764+
if (requestUrl.includes("/FirstradePlatform/actions/variables/RUNTIME_TARGET_JSON")) {
765+
return new Response(JSON.stringify({
766+
value: JSON.stringify({
767+
platform_id: "firstrade",
768+
strategy_profile: "ibit_smart_dca",
769+
dry_run_only: false,
770+
account_scope: "US",
771+
service_name: "firstrade-quant-service",
772+
execution_mode: "live",
773+
}),
774+
}), { status: 200, headers: { "Content-Type": "application/json" } });
775+
}
776+
if (requestUrl.includes("/FirstradePlatform/actions/variables/FIRSTRADE_MIN_RESERVED_CASH_USD")) {
777+
return new Response(JSON.stringify({ value: "50" }), {
778+
status: 200,
779+
headers: { "Content-Type": "application/json" },
780+
});
781+
}
782+
if (requestUrl.includes("/FirstradePlatform/actions/variables/FIRSTRADE_RESERVED_CASH_RATIO")) {
783+
return new Response(JSON.stringify({ value: "0.02" }), {
784+
status: 200,
785+
headers: { "Content-Type": "application/json" },
786+
});
787+
}
788+
if (requestUrl.includes("/FirstradePlatform/actions/variables/DCA_MODE")) {
789+
return new Response(JSON.stringify({ value: "fixed" }), {
790+
status: 200,
791+
headers: { "Content-Type": "application/json" },
792+
});
793+
}
794+
if (requestUrl.includes("/FirstradePlatform/actions/variables/DCA_BASE_INVESTMENT_USD")) {
795+
return new Response(JSON.stringify({ value: "50" }), {
796+
status: 200,
797+
headers: { "Content-Type": "application/json" },
798+
});
799+
}
800+
return new Response("", { status: 404 });
801+
};
802+
try {
803+
const currentStrategies = await __test.loadCurrentStrategies(
804+
{
805+
longbridge: [accountOptions.longbridge[1]],
806+
ibkr: accountOptions.ibkr,
807+
schwab: accountOptions.schwab,
808+
firstrade: accountOptions.firstrade,
809+
},
810+
{ RUNTIME_SETTINGS_DISPATCH_TOKEN: "test-token" },
811+
);
812+
assert.equal(currentStrategies.longbridge.sg.strategy_profile, "tqqq_growth_income");
813+
assert.equal(currentStrategies.longbridge.sg.min_reserved_cash_usd, "25");
814+
assert.equal(currentStrategies.longbridge.sg.reserved_cash_ratio, "0.04");
815+
assert.equal(currentStrategies.longbridge.sg.source, "RUNTIME_TARGET_JSON");
816+
assert.equal(currentStrategies.ibkr["ibkr-primary"].strategy_profile, "tqqq_growth_income");
817+
assert.equal(currentStrategies.ibkr["ibkr-primary"].min_reserved_cash_usd, "150");
818+
assert.equal(currentStrategies.ibkr["ibkr-primary"].reserved_cash_ratio, "0.03");
819+
assert.equal(currentStrategies.ibkr["ibkr-primary"].source, "CLOUD_RUN_SERVICE_TARGETS_JSON");
820+
assert.equal(currentStrategies.schwab.default.strategy_profile, "soxl_soxx_trend_income");
821+
assert.equal(currentStrategies.schwab.default.min_reserved_cash_usd, "150");
822+
assert.equal(currentStrategies.schwab.default.reserved_cash_ratio, "0.03");
823+
assert.equal(currentStrategies.firstrade.default.strategy_profile, "ibit_smart_dca");
824+
assert.equal(currentStrategies.firstrade.default.min_reserved_cash_usd, "50");
825+
assert.equal(currentStrategies.firstrade.default.reserved_cash_ratio, "0.02");
826+
assert.equal(currentStrategies.firstrade.default.dca_mode, "fixed");
827+
assert.equal(currentStrategies.firstrade.default.dca_base_investment_usd, "50");
828+
} finally {
829+
globalThis.fetch = originalFetch;
830+
}
831+
673832
let releaseReservedVariables;
674833
let reservedVariableRequests = 0;
675834
let reservedVariablesFinished = false;

web/strategy-switch-console/worker.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,9 @@ async function fetchWithTimeout(resource, init = {}, timeoutMs = GITHUB_API_TIME
580580
}
581581

582582
async function resolveCurrentStrategyForAccount({ platform, option, optionsCount, repository, readVariable }) {
583-
const serviceTargetsValue = await readVariable(repository, "repository", "", "CLOUD_RUN_SERVICE_TARGETS_JSON");
583+
const serviceTargetsValue = usesServiceTargetsAsRuntimeSource(platform)
584+
? await readVariable(repository, "repository", "", "CLOUD_RUN_SERVICE_TARGETS_JSON")
585+
: "";
584586
const serviceTarget = runtimeTargetFromServiceTargets(serviceTargetsValue, platform, option);
585587
const serviceTargetProfile = cleanCurrentStrategy(serviceTarget?.strategy_profile);
586588
const serviceTargetReservedCashPayload = reservedCashPayloadFromObject(platform, serviceTarget);
@@ -709,6 +711,10 @@ async function resolveCurrentStrategyForAccount({ platform, option, optionsCount
709711
return null;
710712
}
711713

714+
function usesServiceTargetsAsRuntimeSource(platform) {
715+
return platform === "ibkr";
716+
}
717+
712718
function logout(request) {
713719
requireSameOrigin(request, { requireOrigin: true });
714720
return json({ ok: true }, 200, {

0 commit comments

Comments
 (0)