Skip to main content

Set or update per-pair AutoConfig variables for filtered pairs

ยท 7 min read

Gunbot's AutoConfig feature allows for intricate, stateful automation by not only using global variables but also variables specific to each trading pair on an exchange. The setPairVariable object, when used as an action in an AutoConfig job, enables you to create or update these per-pair variables for all pairs that successfully pass the job's defined filters. This allows for highly targeted and adaptive logic.

Use the AutoConfig wizard

Nearly every option that follows can be set without editing files by hand.
Click the โ‹ฎ (three-dots) menu โžœ AutoConfig, step through the wizard, and press Save; it will write a correct autoconfig.json for you.

The setPairVariable Action: Tailoring State to Each Pairโ€‹

The setPairVariable action is a powerful component of AutoConfig jobs that process lists of trading pairs (like manageOverrides, addPairs, removePairs, changeStrategy). If a pair meets all the conditions defined in the job's filters (or filters2, etc.), the instructions within the setPairVariable object are executed for that specific pair.

This means you can:

  • Mark a pair with a status (e.g., lastAction: "bought").
  • Increment a counter specific to that pair (e.g., dcaLevelForThisPair: 2).
  • Store a timestamp relevant to that pair (e.g., cooldownUntilForPairX: 1678886400).

These per-pair variables are stored in autoconfig-pairVariables.json, organized by exchange name, then by pair name, ensuring they are unique and persistent.

Configuration Exampleโ€‹

Let's consider a manageOverrides job that identifies pairs that have just had a buy order (hypothetically detected by other means or a complex custom filter not shown here for brevity) and sets a per-pair variable status to "awaiting_first_sell_target".

{
"markBoughtPairsJob": {
"enabled": true,
"type": "manageOverrides", // This job type iterates through existing pairs
"schedule": "*/1 * * * *", // Runs frequently
"pairs": {
"exchange": "binance",
"include": "USDT-"
},
"filters": {
"justBoughtCondition": { // A filter that identifies pairs recently bought
"filterType": "custom",
"script": "return this.pair && this.pair.lastBuyPrice > 0 && (this.pair.lastSellPrice === 0 || this.pair.lastBuyPrice > this.pair.lastSellPrice);" // Simplified example
}
},
"setPairVariable": { // User setting: Action to set per-pair variables
"status": "awaiting_first_sell_target",
"lastBuyTimestamp": " new Date().getTime() ", // Dynamic value: current timestamp
"initialStopLoss": " this.pair.lastBuyPrice * 0.95 " // Dynamic: 5% below last buy
}
// This job might not even have an 'overrides' section if its sole purpose is to set pair variables
}
}

In the markBoughtPairsJob:

  • For every USDT pair on Binance that passes the justBoughtCondition filter:
    • A per-pair variable named status will be set to the string "awaiting_first_sell_target". So, if USDT-BTC passes, this.pairVariables.binance['USDT-BTC'].status becomes "awaiting_first_sell_target".
    • lastBuyTimestamp for that specific pair will be set to the current Unix timestamp (in milliseconds).
    • initialStopLoss for that pair will be calculated as 95% of its lastBuyPrice (accessed via this.pair.lastBuyPrice because the value string starts with a space).

Later, another AutoConfig job could use a pairVariableExact filter for status: "awaiting_first_sell_target" to find these specific pairs and apply further logic or overrides.

Dynamic Values in setPairVariableโ€‹

As shown in the example, values within setPairVariable can be JavaScript expressions if the string starts with a leading space. This is extremely powerful for per-pair variables, as you can use data from this.pair (the current pair's ledger data), this.variables (global variables), or even this.tickers.

More Dynamic Examples:

"setPairVariable": {
// Increment a pair-specific counter
"buyAttemptsThisCycle": " ( (this.pairVariables[this.exchangeName]?.[this.pairName]?.buyAttemptsThisCycle || 0) + 1 ) ",

// Store a calculated value based on ledger and global variable
"targetSellPrice": " this.pair.lastBuyPrice * (1 + (this.variables.globalProfitTargetPercent || 2) / 100) ",

// Set a boolean flag based on a condition
"isHighRisk": " this.pair.volatility > (this.variables.highRiskVolatilityThreshold || 5) "
}
  • buyAttemptsThisCycle: Safely increments a counter specific to the pair. It reads the existing value (defaulting to 0 if not present), adds 1, and stores it back.
  • targetSellPrice: Calculates a target sell price based on the pair's lastBuyPrice and a global profit target percentage.
  • isHighRisk: Sets a boolean flag for the pair if its (hypothetical) this.pair.volatility is above a global threshold.

resetPairVariable: Conditional Setting for Non-Passing Pairsโ€‹

Similar to resetVariable for global variables, resetPairVariable can be used to set or clear per-pair variables for pairs that were evaluated by the job but did not pass the filter conditions.

{
"statusUpdaterJob": {
// ...
"filters": { "isActiveTradingWindow": { /* ... */ } },
"setPairVariable": { // For pairs passing 'isActiveTradingWindow'
"tradingWindowAlert": false
},
"resetPairVariable": { // For pairs NOT passing 'isActiveTradingWindow'
"tradingWindowAlert": true // Flag these pairs for attention
}
}
}

This ensures that tradingWindowAlert is false for active pairs and true for inactive ones processed by this job.

Key Use Casesโ€‹

  1. Pair-Specific State Machines: Guide a pair through multiple stages (e.g., "bought_dip_1", "bought_dip_2", "target_reached").
  2. Individual Counters/Limits: Track DCA levels, number of consecutive wins/losses, or retry attempts for each pair like USDT-ETH or BTC-ETH.
  3. Storing Pair-Contextual Data: Save calculated indicators, important prices (like first buy price), or timestamps of specific events related to that pair.
  4. Conditional Workflows: Enable complex sequences where one job sets a per-pair variable, and other jobs or even different filter sets within the same job react specifically to that pair's state. For example, if a job identifies that USDT-BTC needs a specific override due to unique conditions, it can set a flag like btcNeedsSpecialOverride: true. A subsequent manageOverrides job can filter for this specific flag on USDT-BTC to apply the change.

Important Pointsโ€‹

  • Context is Key: setPairVariable applies to each pair that passes the filters. Dynamic values using this.pair will correctly reference the data of the specific pair being processed in that iteration.
  • Initialization: When using dynamic expressions to modify existing per-pair variables (like counters), always provide a default using || (e.g., (this.pairVariables[ex]?.[p]?.myCounter || 0) + 1) to handle cases where the variable hasn't been initialized for that pair yet.
  • Data Persistence: Changes are saved to autoconfig-pairVariables.json.
  • Read with pairVariableExact etc.: To use these variables in subsequent filter decisions, employ the pairVariableExact, pairVariableBiggerThan, or pairVariableSmallerThan filter types, or read them in custom scripts using this.pairVariables[this.exchangeName]?.[this.pairName]?.yourVariable.

The setPairVariable action is a cornerstone for creating truly adaptive and intelligent AutoConfig setups that treat each trading pair as an individual entity with its own history and state, leading to more nuanced and potentially more effective automated trading.