Strategy
No description
type Strategy implements Node {
aiHistory(
first: Int
): [AIHistoryEntry!]!
backtestStats: BacktestStats
runningBacktestCount: Int!
versionChainBacktestCount: Int!
analysis: StrategyAnalysis
encryptionStatus: EncryptionStatus!
id: ID!
public: Boolean!
featured: Boolean!
deletedAt: Time
encryptionMode: StrategyEncryptionMode!
keyCustodyBackend: StrategyKeyCustodyBackend!
keyID: String
keyVersion: Int
algorithm: StrategyEncryptionAlgorithm!
encryptedAt: Time
name: String!
description: String
code: String
config: Map!
authoredBy: StrategyStrategyCodeAuthor!
builderMode: StrategyStrategyBuilderMode!
tradingMode: StrategyStrategyTradingMode!
timeframe: String!
stakeCurrency: String!
positionMode: StrategyStrategyPositionMode!
parentID: ID
forkedFromID: ID
originListingID: ID
originOwnerID: String
isLatest: Boolean!
versionNumber: Int!
ownerID: String!
createdAt: Time!
updatedAt: Time!
bots(
after: Cursor
first: Int
before: Cursor
last: Int
orderBy: [BotOrder!]
where: BotWhereInput
): BotConnection!
backtests(
after: Cursor
first: Int
before: Cursor
last: Int
orderBy: [BacktestOrder!]
where: BacktestWhereInput
): BacktestConnection!
simulations(
after: Cursor
first: Int
before: Cursor
last: Int
orderBy: [SimulationOrder!]
where: SimulationWhereInput
): SimulationConnection!
hyperopts(
after: Cursor
first: Int
before: Cursor
last: Int
orderBy: [HyperoptOrder!]
where: HyperoptWhereInput
): HyperoptConnection!
children: [Strategy!]
parent: Strategy
forkedFrom: Strategy
forks: [Strategy!]
biasClearance: BiasClearance!
biasReport: BiasCheckReport
usesFreqai: Boolean!
encryptionLocked: Boolean!
effectiveTradingMode: StrategyStrategyTradingMode!
uiBuilderConfig: UIBuilderConfig
latestVerdict: StrategyVerdict
wrappedDEKs: [WrappedDEK!]!
}
Fields
Strategy.aiHistory ● [AIHistoryEntry!]! non-null object
What the assistant changed on this strategy, across all its versions, newest first.
Strategy.aiHistory.first ● Int scalar
Strategy.backtestStats ● BacktestStats object
Aggregated backtest statistics for this strategy version. Provides best, worst, latest, and average metrics for easy comparison.
Strategy.runningBacktestCount ● Int! non-null scalar
Number of backtests in {running, pending} status for this strategy version. Server-derived at query time. Updates pushed via the strategyBacktestActivity subscription whenever a backtest crosses the active-set boundary — Apollo's normalized cache (Strategy:<id>) picks them up automatically, no client refetch / poll / debounce.
See docs/superpowers/specs/2026-05-13-strategy-running-backtest-count-design.md
Strategy.versionChainBacktestCount ● Int! non-null scalar
How many backtests exist across EVERY version of this strategy's version chain — not just this row's own (#2753).
WHY IT EXISTS: backtests(first: 1) { totalCount } is row-scoped, so a
version the user has just saved honestly reports zero and the strategies-list
card looked like the whole backtest history had been lost. The detail page's
Versions table asks the chain's question and kept showing every run, so the
two surfaces contradicted each other about the same fact.
It cannot be assembled client-side: a per-row chain query on a paginated list is N round trips, and N aliased connections in one document trip the complexity limit.
Chain identity is (name, owning workspace) — the platform's own definition,
the one strategyVersions(name:) uses. Counts every status, exactly as the
connection totalCount it replaces did.
NO OWN DIRECTIVE, like backtestStats and digest: parent-node access
already gates reaching it, and the chain members are scoped to what the
caller could have listed (the owner-or-public predicate tenancy.ScopeBacktests
itself applies). A public version's runs therefore count for a stranger
reading the marketplace, and a private sibling's do not.
Strategy.analysis ● StrategyAnalysis object
Cached analysis blob. Returns Unavailable when not yet computed (resolver lazy-fills).
Strategy.encryptionStatus ● EncryptionStatus! non-null object
Strategy.id ● ID! non-null scalar
Strategy.public ● Boolean! non-null scalar
Whether this resource is publicly visible to all authenticated users
Strategy.featured ● Boolean! non-null scalar
Whether this resource is featured (appears at top of lists)
Strategy.deletedAt ● Time scalar
Soft-delete timestamp. If set, record is considered deleted.
Strategy.encryptionMode ● StrategyEncryptionMode! non-null enum
Trust-ladder encryption mode for this row's sensitive fields. Set at create time; immutable after. Defaults to 'legacy_server' for all rows created before the trust ladder shipped.
Strategy.keyCustodyBackend ● StrategyKeyCustodyBackend! non-null enum
KeyCustodyBackend implementation that produced the wrapping key. Pinned at write time alongside encryption_mode.
Strategy.keyID ● String scalar
Opaque identifier of the wrapping key, backend-specific. Null for legacy_server rows that use the global process key.
Strategy.keyVersion ● Int scalar
Rotation counter for the wrapping key. Null for legacy_server rows; populated when the row is rewrapped under a versioned key.
Strategy.algorithm ● StrategyEncryptionAlgorithm! non-null enum
Symmetric algorithm protecting the row's sensitive fields. Stored alongside the ciphertext so future migrations can retire algorithms without re-encrypting existing rows.
Strategy.encryptedAt ● Time scalar
Timestamp the row's sensitive fields were last encrypted with the current key_id/key_version. Null for legacy_server rows.
Strategy.name ● String! non-null scalar
Strategy name (not unique, allows versions)
Strategy.description ● String scalar
Strategy description
Strategy.code ● String scalar
Python strategy code (server-derived for ui builder_mode; required for code mode — enforced in the strategy domain, see ADR-0088)
Strategy.config ● Map! non-null scalar
Strategy-specific configuration (config.json) - REQUIRED
Strategy.authoredBy ● StrategyStrategyCodeAuthor! non-null enum
Who wrote this version's code: user, or assistant (the assistant's code-edit card). Assistant code must pass a bias check before it is applied or judged.
Strategy.builderMode ● StrategyStrategyBuilderMode! non-null enum
Strategy editing mode: 'ui' for UI builder (code generated from config), 'code' for direct Python editing
Strategy.tradingMode ● StrategyStrategyTradingMode! non-null enum
Mirrored from config.trading_mode — normalized uppercase so it can be filtered/indexed
Strategy.timeframe ● String! non-null scalar
Freqtrade timeframe (e.g. '5m', '1h'), default '5m'. Written THROUGH to config.timeframe, the source of truth; a conflict is rejected.
Strategy.stakeCurrency ● String! non-null scalar
Mirrored from config.stake_currency (e.g. 'USDT', 'BTC') — default 'USDT'
Strategy.positionMode ● StrategyStrategyPositionMode! non-null enum
Mirrored from ui_builder_config.position_mode for UI strategies; defaults LONG_AND_SHORT for code strategies
Strategy.parentID ● ID scalar
Parent strategy ID for versioning (null for root v1)
Strategy.forkedFromID ● ID scalar
Original strategy ID this was forked from (null if not forked)
Strategy.originListingID ● ID scalar
Marketplace listing whose content this version still carries unedited by a person (null once a person edits it)
Strategy.originOwnerID ● String scalar
Owner of another organization whose content this version still carries unedited by a person (null once a person edits it)
Strategy.isLatest ● Boolean! non-null scalar
Indicates if this is the latest version of the strategy
Strategy.versionNumber ● Int! non-null scalar
Auto-incremented version number
Strategy.ownerID ● String! non-null scalar
Group ID (organization) that owns this strategy
Strategy.createdAt ● Time! non-null scalar
Strategy.updatedAt ● Time! non-null scalar
Strategy.bots ● BotConnection! non-null object
Strategy.bots.after ● Cursor scalar
Returns the elements in the list that come after the specified cursor.
Strategy.bots.first ● Int scalar
Returns the first _n_ elements from the list.
Strategy.bots.before ● Cursor scalar
Returns the elements in the list that come before the specified cursor.
Strategy.bots.last ● Int scalar
Returns the last _n_ elements from the list.
Strategy.bots.orderBy ● [BotOrder!] list input
Ordering options for Bots returned from the connection.
Strategy.bots.where ● BotWhereInput input
Filtering options for Bots returned from the connection.
Strategy.backtests ● BacktestConnection! non-null object
Strategy.backtests.after ● Cursor scalar
Returns the elements in the list that come after the specified cursor.
Strategy.backtests.first ● Int scalar
Returns the first _n_ elements from the list.
Strategy.backtests.before ● Cursor scalar
Returns the elements in the list that come before the specified cursor.
Strategy.backtests.last ● Int scalar
Returns the last _n_ elements from the list.
Strategy.backtests.orderBy ● [BacktestOrder!] list input
Ordering options for Backtests returned from the connection.
Strategy.backtests.where ● BacktestWhereInput input
Filtering options for Backtests returned from the connection.
Strategy.simulations ● SimulationConnection! non-null object
Strategy.simulations.after ● Cursor scalar
Returns the elements in the list that come after the specified cursor.
Strategy.simulations.first ● Int scalar
Returns the first _n_ elements from the list.
Strategy.simulations.before ● Cursor scalar
Returns the elements in the list that come before the specified cursor.
Strategy.simulations.last ● Int scalar
Returns the last _n_ elements from the list.
Strategy.simulations.orderBy ● [SimulationOrder!] list input
Ordering options for Simulations returned from the connection.
Strategy.simulations.where ● SimulationWhereInput input
Filtering options for Simulations returned from the connection.
Strategy.hyperopts ● HyperoptConnection! non-null object
Strategy.hyperopts.after ● Cursor scalar
Returns the elements in the list that come after the specified cursor.
Strategy.hyperopts.first ● Int scalar
Returns the first _n_ elements from the list.
Strategy.hyperopts.before ● Cursor scalar
Returns the elements in the list that come before the specified cursor.
Strategy.hyperopts.last ● Int scalar
Returns the last _n_ elements from the list.
Strategy.hyperopts.orderBy ● [HyperoptOrder!] list input
Ordering options for Hyperopts returned from the connection.
Strategy.hyperopts.where ● HyperoptWhereInput input
Filtering options for Hyperopts returned from the connection.
Strategy.children ● [Strategy!] list object
Child strategy versions derived from this strategy (self-referential, via parent_id)
Strategy.parent ● Strategy object
Strategy.forkedFrom ● Strategy object
Original strategy this was forked from
Strategy.forks ● [Strategy!] list object
Strategies forked from this one
Strategy.biasClearance ● BiasClearance! non-null enum
Whether this version's code may be judged and applied, as far as bias goes (T-P4-IM-02).
Strategy.biasReport ● BiasCheckReport object
The conclusive bias check the clearance rests on, when there is one.
Strategy.usesFreqai ● Boolean! non-null scalar
Whether the strategy config uses FreqAI (a freqaimodel or freqai block). Server-derived from the config the caller's read decrypted; false when the config is passphrase-sealed and the session cannot open it.
Strategy.encryptionLocked ● Boolean! non-null scalar
True when the strategy has at least one passphrase-encrypted IP field (code / config / ui_builder_config / analysis) that the current session could not decrypt. Editors must surface an unlock prompt and refuse Save while this is true.
Strategy.effectiveTradingMode ● StrategyStrategyTradingMode! non-null enum
The market this strategy actually runs on: the stored Freqtrade
config.trading_mode when it declares one, otherwise the mirrored
tradingMode column (which carries a UI-builder strategy's mode). Same
resolution the backtest and hyperopt spec builders apply, so this is the
market the container will be dispatched on.
Read THIS to decide anything market-dependent — pair scope, stake
currencies, readiness, the mode chip. Do not re-derive it from config,
and prefer it over tradingMode, which is a SQL-filterable mirror and can
lag the config.
Never null: a strategy that declares no mode anywhere runs on Freqtrade's
own default for an absent trading_mode, which is SPOT.
Strategy.uiBuilderConfig ● UIBuilderConfig object
UI builder configuration — only present for builder_mode='ui' strategies
Strategy.latestVerdict ● StrategyVerdict object
The most recent D6 verdict for this version, or null when it was never evaluated.
Strategy.wrappedDEKs ● [WrappedDEK!]! non-null object
All envelopes wrapping the strategy's DEK to a passkey public key. Populated only when the strategy is encrypted under T2.2; empty list means the strategy is either plaintext or encrypted under an earlier trust tier (T1.1 passphrase, T1.4 strict mode).
Authorization piggybacks on the parent Strategy.@hasScope check — this list is opaque ciphertext, but exposing it across orgs would reveal who has access, so we restrict to the resource's own view-scope holders.
Interfaces
Node interface
An object with an ID. Follows the Relay Global Object Identification Specification
Returned By
applyHyperoptParamsToStrategy mutation ● applyStrategyVersion mutation ● convertStrategyToBuilder mutation ● convertStrategyToCode mutation ● createStrategy mutation ● createStrategyWithPassphrase mutation ● decryptStrategyOnce mutation ● forkFromListing mutation ● forkStrategy mutation ● renameStrategy mutation ● restoreStrategyVersion mutation ● setStrategyFeatured mutation ● setStrategyUIBuilderEncrypted mutation ● setStrategyVisibility mutation ● strategy query ● strategyBacktestActivity subscription ● strategyVersions query ● updateStrategy mutation ● updateStrategyCodeWithPassphrase mutation ● updateStrategyWithPassphrase mutation
Member Of
Backtest object ● Bot object ● Hyperopt object ● Simulation object ● Strategy object ● StrategyChangeProposal object ● StrategyCodeChangeProposal object ● StrategyEdge object