diff --git a/.env b/.env
index e31db3d33..18d1741f2 100644
--- a/.env
+++ b/.env
@@ -31,7 +31,7 @@ TS_PUBLIC_TYPESENSE_API_URL=https://typesense.tradingstrategy.ai
TS_PUBLIC_TYPESENSE_API_KEY=npdPPJNELDhdr7v6IS9rQUpFG2VvdyAL
TS_PUBLIC_DISCORD_URL=https://discord.gg/5M88m9nM8H
TS_PUBLIC_WALLET_CONNECT_PROJECT_ID=9ee7efad98897eb60ba023db6aa72355
-TS_PUBLIC_STRATEGIES='[{"id":"enzyme-polygon-eth-btc-rsi","name":"ETH-BTC price surge","url":"https://enzyme-polygon-eth-btc-rsi.tradingstrategy.ai/","frontpage":true},{"id":"enzyme-ethereum-btc-eth-stoch-rsi","name":"Stochastic ETH/BTC long","url":"https://enzyme-ethereum-btc-eth-stoch-rsi.tradingstrategy.ai","fees":{"trading_strategy_protocol_fee":0.02,"strategy_developer_fee":0.1},"frontpage":true},{"id":"enzyme-polygon-eth-rolling-ratio","name":"ETH/BTC rolling ratio","url":"https://enzyme-polygon-eth-rolling-ratio.tradingstrategy.ai/","fees":{"trading_strategy_protocol_fee":0.02,"strategy_developer_fee":0.05},"frontpage":true},{"id":"enzyme-polygon-matic-eth-usdc","name":"ETH-MATIC-USDC momentum","url":"https://enzyme-polygon-matic-eth-usdc.tradingstrategy.ai","frontpage":true},{"id":"enzyme-polygon-eth-btc-usdc","name":"ETH-BTC-USDC momentum","url":"https://enzyme-polygon-eth-btc-usdc.tradingstrategy.ai","new_version_id":"enzyme-polygon-eth-btc-rsi","frontpage":true},{"id":"enzyme-polygon-matic-usdc","name":"MATIC breakout","url":"https://enzyme-polygon-matic-usdc.tradingstrategy.ai"},{"id":"enzyme-polygon-eth-breakout","name":"ETH breakout","url":"https://enzyme-polygon-eth-breakout.tradingstrategy.ai"},{"id":"enzyme-polygon-eth-usdc","name":"ETH Breakout bounce","url":"https://enzyme-polygon-eth-usdc.tradingstrategy.ai"},{"id":"enzyme-polygon-eth-usdc-sls","name":"ETH Balance snap","url":"https://enzyme-polygon-eth-usdc-sls.tradingstrategy.ai"},{"id":"polygon-eth-spot-short","name":"ETH mean reversion bounce","url":"https://polygon-eth-spot-short.tradingstrategy.ai"},{"id":"arbitrum-btc-breakout","name":"BTC Barrier Breach","url":"https://arbitrum-btc-breakout.tradingstrategy.ai"}]'
+TS_PUBLIC_STRATEGIES='[{"id":"enzyme-polygon-eth-btc-rsi","name":"ETH-BTC price surge","url":"https://enzyme-polygon-eth-btc-rsi.tradingstrategy.ai/","frontpage":true,"hiddenPositions":[4]},{"id":"enzyme-ethereum-btc-eth-stoch-rsi","name":"Stochastic ETH/BTC long","url":"https://enzyme-ethereum-btc-eth-stoch-rsi.tradingstrategy.ai","fees":{"trading_strategy_protocol_fee":0.02,"strategy_developer_fee":0.1},"frontpage":true},{"id":"enzyme-polygon-eth-rolling-ratio","name":"ETH/BTC rolling ratio","url":"https://enzyme-polygon-eth-rolling-ratio.tradingstrategy.ai/","fees":{"trading_strategy_protocol_fee":0.02,"strategy_developer_fee":0.05},"frontpage":true},{"id":"enzyme-polygon-matic-eth-usdc","name":"ETH-MATIC-USDC momentum","url":"https://enzyme-polygon-matic-eth-usdc.tradingstrategy.ai","frontpage":true},{"id":"enzyme-polygon-eth-btc-usdc","name":"ETH-BTC-USDC momentum","url":"https://enzyme-polygon-eth-btc-usdc.tradingstrategy.ai","new_version_id":"enzyme-polygon-eth-btc-rsi","frontpage":true},{"id":"enzyme-polygon-matic-usdc","name":"MATIC breakout","url":"https://enzyme-polygon-matic-usdc.tradingstrategy.ai"},{"id":"enzyme-polygon-eth-breakout","name":"ETH breakout","url":"https://enzyme-polygon-eth-breakout.tradingstrategy.ai"},{"id":"enzyme-polygon-eth-usdc","name":"ETH Breakout bounce","url":"https://enzyme-polygon-eth-usdc.tradingstrategy.ai"},{"id":"enzyme-polygon-eth-usdc-sls","name":"ETH Balance snap","url":"https://enzyme-polygon-eth-usdc-sls.tradingstrategy.ai"},{"id":"polygon-eth-spot-short","name":"ETH mean reversion bounce","url":"https://polygon-eth-spot-short.tradingstrategy.ai"},{"id":"arbitrum-btc-breakout","name":"BTC Barrier Breach","url":"https://arbitrum-btc-breakout.tradingstrategy.ai"}]'
TS_PUBLIC_GEO_BLOCK='{"strategies:view":["CU","IR","KP","RU","SY"],"strategies:deposit":["CU","IR","KP","RU","SY","US","UK"]}'
# Uncomment to test chain maintenance error
# TS_PUBLIC_CHAINS_UNDER_MAINTENANCE='{ "binance": "BNB Chain" }'
diff --git a/src/lib/explorer/TradingDescription.svelte b/src/lib/explorer/TradingDescription.svelte
index e8aa84307..bf07780ec 100644
--- a/src/lib/explorer/TradingDescription.svelte
+++ b/src/lib/explorer/TradingDescription.svelte
@@ -19,13 +19,15 @@ Used in DataTable context (vs. standard svelte component context).
-
+
{label}
diff --git a/src/lib/trade-executor/strategy/configuration.ts b/src/lib/trade-executor/strategy/configuration.ts
index fdf7bcfaf..974f85fcf 100644
--- a/src/lib/trade-executor/strategy/configuration.ts
+++ b/src/lib/trade-executor/strategy/configuration.ts
@@ -1,6 +1,6 @@
import { strategyConfig } from '$lib/config';
import { z } from 'zod';
-import { percent } from '../state/utility-types';
+import { percent, primaryKey } from '../state/utility-types';
export const strategyFeesSchema = z.object({
management_fee: percent.default(0),
@@ -16,7 +16,8 @@ export const strategyConfigurationSchema = z.object({
url: z.string().url(),
fees: strategyFeesSchema.default({}),
new_version_id: z.string().nullish(),
- frontpage: z.boolean().nullish()
+ frontpage: z.boolean().nullish(),
+ hiddenPositions: primaryKey.array().default([])
});
export type StrategyConfiguration = z.infer
;
diff --git a/src/routes/strategies/[strategy]/[status=positionStatus]-positions/+page.svelte b/src/routes/strategies/[strategy]/[status=positionStatus]-positions/+page.svelte
index 9687c8661..b08bef3ba 100644
--- a/src/routes/strategies/[strategy]/[status=positionStatus]-positions/+page.svelte
+++ b/src/routes/strategies/[strategy]/[status=positionStatus]-positions/+page.svelte
@@ -45,6 +45,7 @@
{...options}
hasPagination={status === 'closed'}
hasSearch={status === 'closed'}
+ hiddenPositions={strategy.hiddenPositions}
on:change={handleChange}
/>
{:else}
diff --git a/src/routes/strategies/[strategy]/[status=positionStatus]-positions/+page.ts b/src/routes/strategies/[strategy]/[status=positionStatus]-positions/+page.ts
index 137016149..6fad821cb 100644
--- a/src/routes/strategies/[strategy]/[status=positionStatus]-positions/+page.ts
+++ b/src/routes/strategies/[strategy]/[status=positionStatus]-positions/+page.ts
@@ -3,9 +3,14 @@ import { getTradingPositionInfoArray } from 'trade-executor/state/position-info.
export async function load({ params, parent }) {
// status can be `open`, `closed` or `frozen` (see params/positionStatus.ts)
const { status } = params;
- const { state } = await parent();
+ const { admin, strategy, state } = await parent();
+ const { hiddenPositions } = strategy;
- const positions = getTradingPositionInfoArray(state, status);
+ let positions = getTradingPositionInfoArray(state, status);
+
+ if (!admin) {
+ positions = positions.filter((p) => !hiddenPositions.includes(p.position_id));
+ }
return { positions, status };
}
diff --git a/src/routes/strategies/[strategy]/[status=positionStatus]-positions/FlagCell.svelte b/src/routes/strategies/[strategy]/[status=positionStatus]-positions/FlagCell.svelte
index 82e614945..877fffd85 100644
--- a/src/routes/strategies/[strategy]/[status=positionStatus]-positions/FlagCell.svelte
+++ b/src/routes/strategies/[strategy]/[status=positionStatus]-positions/FlagCell.svelte
@@ -8,6 +8,7 @@
export let admin = false;
export let position: TradingPositionInfo;
export let baseUrl: string;
+ export let isHidden = false;
function getTradeLink(trade: TradeInfo) {
return `${baseUrl}/trade-${trade.trade_id}`;
@@ -83,6 +84,19 @@
{/if}
+
+ {#if admin && isHidden}
+
+
+ This info is only displayed to admin users.
+
+ This position is hidden from non-admin users.
+
+ Hidden positions are configured in frontend
strategy configuration (on production, in the
+ strategy.json
config file).
+
+
+ {/if}
diff --git a/src/routes/strategies/[strategy]/[status=positionStatus]-positions/PositionTable.svelte b/src/routes/strategies/[strategy]/[status=positionStatus]-positions/PositionTable.svelte
index 14bf0d947..342dfd1e1 100644
--- a/src/routes/strategies/[strategy]/[status=positionStatus]-positions/PositionTable.svelte
+++ b/src/routes/strategies/[strategy]/[status=positionStatus]-positions/PositionTable.svelte
@@ -21,6 +21,7 @@
export let direction: 'asc' | 'desc' = 'desc';
export let hasSearch = false;
export let hasPagination = false;
+ export let hiddenPositions: number[] = [];
const positionsStore = writable([] as TradingPositionInfo[]);
$: positionsStore.set(positions);
@@ -53,7 +54,12 @@
table.column({
header: 'Position',
id: 'description',
- accessor: ({ pair, isTest }) => ({ label: pair.symbol, modifier: pair.kindShortLabel, isTest }),
+ accessor: ({ position_id, pair, isTest }) => ({
+ class: hiddenPositions.includes(position_id) ? 'hidden' : '',
+ label: pair.symbol,
+ modifier: pair.kindShortLabel,
+ isTest
+ }),
cell: ({ value }) => createRender(TradingDescription, value)
}),
table.column({
@@ -61,7 +67,12 @@
id: 'flags',
accessor: (position) => position,
cell: ({ value }) =>
- createRender(FlagCell, { admin, position: value, baseUrl: `./${status}-positions/${value.position_id}` }),
+ createRender(FlagCell, {
+ admin,
+ position: value,
+ baseUrl: `./${status}-positions/${value.position_id}`,
+ isHidden: hiddenPositions.includes(value.position_id)
+ }),
plugins: { sort: { disable: true } }
}),
table.column({
@@ -141,6 +152,23 @@
}
.position-table :global {
+ /* Make "hidden" position rows look 50% opaque w/out breaking nested tooltip style */
+ tr:has(.hidden) {
+ td {
+ background: var(--c-box-1);
+ }
+
+ /* only apply color-mix to text in leaf nodes */
+ *:not(:has(> *)) {
+ color: color-mix(in srgb, currentColor, var(--c-body) 50%);
+ }
+
+ /* revert the color-mix 50% opacity for the tooltip */
+ .tooltip .popup * {
+ color: var(--c-text);
+ }
+ }
+
.ticker {
white-space: pre;
}