Skip to main content

AutoConfig filter types

AutoConfig jobs support various filter types. These include:

TypeUsage
Ticker filtersUsed for jobs that require external data.
Pair state filtersUsed for jobs that require internal data.
Generic filtersUsed for all job types.
User VariablesThis is not a filter category category of, instead it is data that can be stored and retrieved from within any job.
User variables can be filtered, and accessed by other jobs than the one that saved them.

Ticker filters

Ticker filters request data from exchange tickers at the time the job runs. Different types of filters can be applied to add or remove pairs, but not all filter types work on every exchange due to varying availability of required data. For example, on Huobi AutoConfig, last price is used instead of bid/ask for all price-related filters.

The following table provides an overview of available filter types with their descriptions and any additional details.

TypeDescriptionExtras
minPriceReturns true if the price is higher than set.n/a
maxPriceReturns true if the price is lower than set.n/a
minPricePctChangeIntervalReturns true if the current price is at least x% higher than the average price of all snapshots.lastSnapshots
maxPricePctChangeIntervalReturns true if the current price is at least x% lower than the average price of all snapshots.lastSnapshots
minVolumePctChangeIntervalReturns true if the current 24h volume is at least x% higher than the average 24h volume of all snapshots.lastSnapshots
maxVolumePctChangeIntervalReturns true if the current 24h volume is at least x% lower than the average 24h volume of all snapshots.lastSnapshots
minVolume24hReturns true if the 24h volume is higher than set (volume in base).n/a
maxVolume24hReturns true if the 24h volume is lower than set (volume in base).n/a
minVolatilityPct24hReturns true if the 24h price percentage change is higher than set.n/a
maxVolatilityPct24hReturns true if the 24h price percentage change is lower than set.n/a
minSpreadPctReturns true if the percentage difference between bid and ask is higher than set.n/a
maxSpreadPctReturns true if the percentage difference between bid and ask is lower than set.n/a
minSlopePctIntervalReturns true if the slope for all prices in snapshots is bigger than set.lastSnapshots
maxSlopePctIntervalReturns true if the slope for all prices in snapshots is smaller than set (executed only when max snapshot sample size is reached).lastSnapshots
minStandardDevPctIntervalReturns true if the standard deviation for all prices in snapshots is bigger than set (executed only when max snapshot sample size is reached).lastSnapshots
maxStandardDevPctIntervalReturns true if the standard deviation for all prices in snapshots is smaller than set (executed only when max snapshot sample size is reached).lastSnapshots
minVolumeRankReturns true if a pair's 24h volume rank (rankings are specific per base) is higher than set.n/a
maxVolumeRankReturns true if a pair's 24h volume rank (rankings are specific per base) is lower than set.n/a
bullishStandardDeviationChannelReturns true if the price is within a defined range from the lower band and other conditions are met (detects downwards breakout from upwards channel).lastSnapshots
bearishStandardDeviationChannelReturns true if the price is within a defined range from the upper band and other conditions are met (detects upwards breakout from downwards channel).lastSnapshots
linearRegressionChannelReturns true if the price is within a defined range from the lower band and other conditions are met (same as "Linear regression" indicator on TradingView).lastSnapshots
tip

If you collect 48 ticker snapshots and the job runs every five minutes, that means any *Interval job works with 4h of market data (48 x 5).

Note that some filters have additional parameters that must be set to function properly. The minPricePctChangeInterval and maxPricePctChangeInterval filters require the lastSnapshots parameter to calculate the average price of all snapshots.

The lastSnapshots input allows you to select a specific number of recent snapshots to use for calculating a filter. For instance, if your task generates 100 snapshots but you only want to use the last 10 snapshots to calculate slope for a particular filter, you can specify this using lastSnapshots.

Filter notation examples

"spread": {
"type": "minSpreadPct",
"min": 0.5
},
"volume": {
"type": "belowMedianVolume"
},
"stdev": {
"type": "maxStandardDevPctInterval",
"max": 0.3
},
"channel": {
"type": "bullishStandardDeviationChannel",
"range": -10
},
"maxStandardDevPctInterval": {
"type": "minVolumePctChangeInterval",
"max": 1,
"lastSnapshots": 3
}
"hedge": {
"type": "allowsHedging",
"BTC": "USDT"
}

Trailing filters

Trailing filters are ticker filters that trail down prices or volume. There are three types of trailing filters: buyTrailing, volumeTrailing, and slopeTrailing. Buy trailing is similar to a regular Gunbot strategy and can be used to add pairs to your configuration only after they have hit their trailing stop. This is useful for trailing massive numbers of pairs without the downsides of long cycling times.

Note that these filter types can only be used in addPairs jobs on exchanges that provide ask prices or volume in tickers, and only work when used in the first filter set of a job.

Here's an example configuration for buy trailing:

  • Collect up to 60 ticker snapshots, adding a new snapshot every time the job runs (every minute).
  • Use the 60 collected bid prices for a pair to calculate an EMA.
  • Continuously trail down all pairs using a trailingRange of 1% of the ask price.
  • The filter passes when the ask prices cross over the trailing stop while being below buyLevel (which is a percentage below the EMA calculated by this filter).

Volume trailing works the same as buy trailing, but base volume is used where prices are used in buy trailing. Slope trailing works like buy trailing but trails the slope percentage of a pair. Buy level is based on the same EMA as it is for buy trailing.

{
"trailingExample": {
"pairs": {
"exclude": "",
"include": "BTC-,USDT-",
"maxPairs": 10,
"exchange": "binance"
},
"filters": {
"trailing": {
"type": "buyTrailing",
"buyLevel": 0.5,
"trailingRange": 1
}
},
"schedule": "* * * * *",
"type": "addPairs",
"strategy": "instantBuy",
"enabled": true,
"resume": true,
"snapshots": 60
},

Ticker history filters

Most ticker filters are also available as *History variant. These work in the same way as described above, but they use a different data set as input. Available history filters:

  • minPriceHistory
  • maxPriceHistory
  • maxVolumeRankHistory
  • minVolumeRankHistory
  • minPricePctChangeIntervalHistory
  • maxPricePctChangeIntervalHistory
  • minVolumePctChangeIntervalHistory
  • maxVolumePctChangeIntervalHistory
  • minVolume24hHistory
  • maxVolume24hHistory
  • minVolatilityPct24hHistory
  • maxVolatilityPct24hHistory
  • minSpreadPctHistory
  • maxSpreadPctHistory
  • minSlopePctIntervalHistory
  • maxSlopePctIntervalHistory
  • minStandardDevPctIntervalHistory
  • maxStandardDevPctIntervalHistory
  • bearishStandardDeviationChannelHistory
  • bullishStandardDeviationChannelHistory

History filters take one additional input, defining which history data should be used. the config for a history filter looks like:

"filter": {
"type": "minPriceHistory",
"min": 10,
"historySource": 6
}

The historySource parameter in the example above means that it will use the price of the history entry with number 6. The oldest history entry has number 0.

How the history is built up is defined by the following parameters in the root level:

"history": 7,
"historyInterval": 15,

The example above would collect 7 history entries, with a minimum interval of 15 minutes.

New history entries are saved as follows:

  • When there is no history, the oldest ticker snapshot will be added as first history entry.
  • When there is at least one history entry, a new one is added when the time difference between the oldest ticker snapshot and the latest history entry is bigger than the time defined in historyInterval. The oldest ticker snapshot will be added as newest history entry. In case the maximum number of history entries is reached, the oldest history entry will get deleted once a new one gets added.

The config example below shows a job that filters for:

  • BTC pairs that currently ranks top10 for 24h volume
  • The 5 history entries have a slope of at least 1%
  • Pair must have ranked top10 24h volume in the oldest history entry
If oldest snapshot is > 60 minutes older than newest history entry, 
it gets moved to history

Snapshots, 1m interval
[s] [s] [s] [s] [s]
History entries, 60m interval |
[0] [1] [2] [3] [4] |
^-----------------------*


"addMoon": {
"pairs": {
"exclude": "",
"include": "BTC-",
"maxPairs": 10,
"exchange": "binance"
},
"filters": {
"filter1": {
"type": "maxVolumeRank",
"max": 10
},
"filter2": {
"type": "minSlopePctIntervalHistory",
"min": 1,
"historySource": 4
},
"filter3": {
"type": "maxVolumeRankHistory",
"max": 10,
"historySource": 0
}
},
"schedule": "* * * * * *",
"type": "addPairs",
"strategy": "moon",
"snapshots": 5,
"history": 5,
"historyInterval": 60,
"resume": true
},

tip

Both snapshots and history cause a relatively high load on I/O operations. Depending on your system, allowing for too many saved entries can negatively impact performance.

Pair state filters

State filters in Gunbot use data from the internal ledger to filter pairs that have already cycled since the last (re)start. State data includes indicator values, balance data, candle data, and much more.

TypeDescription
exactExact match between value and key in config and pair state; returns true when key and value match exactly.
biggerThanValue for key in pair state must be bigger than in config; returns true when emal in state is bigger than 0.25.
smallerThanValue for key in pair state must be smaller than in config; returns true when emal in state is smaller than 0.2.
compareBiggerCompares values for two keys in state, values in config are irrelevant; returns true when emal is bigger than ema2 in state.
compareSmallerCompares values for two keys in state, values in config are irrelevant; returns true when emal is smaller than ema2 in state.
differenceBiggerCompares values for two keys in state, values in config are irrelevant; returns true when percentage difference between emal and ema2 is bigger than delta (%).
differenceSmallerCompares values for two keys in state, values in config are irrelevant; returns true when percentage difference between emal and ema2 is smaller than delta (%).

Formula used in differenceBigger:
100 * ((ema2 - ema1) / ema1) > delta

Formula used in differenceSmaller:
100 * ((ema2 - ema1) / ema1) < delta

Please note that the ema1 and ema2 keys used in the formula examples can be replaced with any two keys. Just make sure you understand the positions of the keys to be compared in the configuration file because they matter.

Generic filters

Generic filters can be used with any job type, whether it primarily uses ticker or state filters. Here are the available filters:

Filter TypeDescription
variableExactReturns true when the variable value is exactly as defined.
variableNotExistReturns true when the variable key does not yet exist.
variableBiggerThanReturns true when the variable value is bigger than the target.
variableSmallerThanReturns true when the variable value is smaller than the target.
pairVariableSmallerThanReturns true when the pair-specific variable value is smaller than the target.
pairVariableBiggerThanReturns true when the pair-specific variable value is bigger than the target.
pairVariableExactReturns true when the pair-specific variable is exactly as defined. Can use an extra exchange input to check pair variables for another exchange.
strategyNameReturns true when the strategy of an enabled pair is similar to the defined strategy name.
minTimeInConfigReturns true when the pair has been in the config for longer than a set number of minutes.
maxTimeInConfigReturns true when the pair has not been in the config for longer than a set number of minutes.
customAllows you to use any custom JavaScript expression. The filter passes when the expression returns true.

Generic filter examples:

"Seconds since last order": {
"type": "custom",
"target": " (function timeCheck(data){if(typeof data.orders==='undefined'){return false;} else if(typeof data.orders[0]==='undefined'){return false;} const lastOrderTime=data.orders[0].time;const secondsSinceLastOrder=(Date.now()-lastOrderTime)/1000;if(secondsSinceLastOrder<180){return true;}})(this)"
},
"Price and EMA": {
"type": "custom",
"target": " this.pair.ema1 > this.pair.Bid"
},
"time": {
"type": "minTimeInConfig",
"min": 60
},
"time": {
"type": "maxTimeInConfig",
"max": 90
} ,
"var": {
"type": "variableNotExist",
"hedge": "BTC"
},
"strat": {
"type": "strategyName",
"name": "moon"
},

User variables

Gunbot allows you to define user variables for each job, which can be used for filtering in other jobs. You can use global variables and pair-specific variables to create more complex filter setups.

By using user variables, you can avoid repeating multiple filter conditions across multiple jobs and make job dependencies possible. For example, one job can monitor a specific condition and set a variable like liquidationStop: true when its conditions are met. Other jobs that depend on this liquidation stop can then set one filter looking for an exact match for liquidationStop: true, instead of repeating the same filters set in the job that monitors the distance between price and liquidation price.

A job sets a variable when at least one pair passes all filters for this job, and setVariable is defined in the job's configuration. User variables can hold true/false values, number values, or strings, and the new value will overwrite the old one if it was previously set with a different value.

To set a global variable:

"setVariable": {
"userVariable1": true
},

To set pair specific variables, use a block like this:

"setPairVariable": {
"awesomeVariable": true,
"evenBetter": true
},

All variables are written to a file and imported upon Gunbot restarts, but file corruption can occur in certain situations. Therefore, it's recommended to not fully depend on saved variables and run the jobs that set them relatively frequently. It's a good practice to save absolutely critical data as a pair override in the config itself.

To read a variable, use the filter type variableExact. It can be used in all job types.

"filter": {
"type": "variableExact",
"userVariable1": true
}

The filter type for user variables is an exact match only, which returns true when userVariable1 has a value of true.

air variables can be read with a filter like this:

"pairVar": {
"type": "pairVariableExact",
"awesomeVariable": true
}

The same job that sets a variable can also reset it when no pairs pass all filters; this option is called resetVariable. It can contain one or more variables whose value can be filtered as an exact match, similar to setting a variable.

resetVariable looks like this:

"resetVariable": {
"userVariable1": true
}

To reset pair specific variables, use a block like this:

"resetPairVariable": {
"awesomeVariable": false,
"evenBetter": false
}
tip

It's worth noting that variables are entirely optional, and no problem exists when no setVariable exists in a job.

Multiple filter sets

Instead of using a single set of filters, you can also add multiple sets of filters in a job.

Use this when you want to monitor for different conditions in a single job, if a pair passes all filters in any of the filter sets, changes are made.

Besides the obligatory first set of filters, you can add up to 9 more sets. named filters2 to filters10

Config example:

{
"example": {
"pairs": {
"exclude": "",
"include": "",
"maxPairs": 500,
"noBag": false,
"exchange": "binance"
},
"filters": {
"price": {
"type": "minPrice",
"min": 0.0000001
}
},
"filters2": {
"minVolume24h": {
"type": "minVolume24h",
"min": 100
}
},
"schedule": "*/30 * * * * *",
"type": "removePairs",
"enabled": true
}
}