Actions

Actions are the building blocks of your strategy. Each action defines what the bot should do when its trigger conditions are met. A strategy can have any number of actions, and each is evaluated independently on every candle.

The Three Action Types

Botmarley supports three action types, each serving a distinct purpose in the lifecycle of a trade:

flowchart LR
    A["open_long<br/>Open new position"] --> B["buy<br/>Add to position (DCA)"]
    B --> C["sell<br/>Exit position"]

    style A fill:#22c55e,color:#fff
    style B fill:#4a9eff,color:#fff
    style C fill:#ef4444,color:#fff

open_long -- Open a New Position

The open_long action creates a new position by buying an asset. This is the entry point of any trade.

When to use: Use open_long for the initial entry into a trade. This action only fires when there is no existing open position (or when max_open_positions has not been reached).

Example:

[[actions]]
type = "open_long"
amount = "100 USDC"
average_price = false

  [[actions.triggers]]
  indicator = "rsi_14"
  operator = "<"
  target = "30"

This opens a new position worth 100 USDC when RSI(14) drops below 30.

Note

open_long is the only action type that creates a new position. If you already have an open position and want to add more, use buy instead.


buy -- Add to an Existing Position (DCA)

The buy action adds to an already open position. This is how you implement Dollar-Cost Averaging (DCA) -- buying more when the price drops to lower your average entry price.

When to use: Use buy to add to a position that was opened by open_long. This action only fires when a position is already open.

Example:

[[actions]]
type = "buy"
amount = "200 USDC"
average_price = true

  [[actions.triggers]]
  type = "pos_price_change"
  value = "-2%"
  max_count = 1

This adds 200 USDC to the existing position when the price drops 2% from the entry price. The average_price = true flag means the entry price is recalculated (see average_price explained below). The max_count = 1 ensures this DCA level only triggers once per position.


sell -- Exit a Position

The sell action exits part or all of an open position. You can sell a percentage of your position or sell everything.

When to use: Use sell for taking profit, cutting losses (stop-loss), or any exit condition.

Example -- partial exit:

[[actions]]
type = "sell"
amount = "50%"

  [[actions.triggers]]
  indicator = "rsi_14"
  operator = ">"
  target = "50"

This sells half the position when RSI rises above 50, locking in partial profit while letting the rest ride.

Example -- full exit:

[[actions]]
type = "sell"
amount = "100%"

  [[actions.triggers]]
  type = "pos_price_change"
  value = "3%"

This sells the entire position when the price rises 3% from entry, closing the trade completely.


Amount Formats

Every action requires an amount field that specifies how much to buy or sell. Botmarley supports two formats:

Fixed Amount: "100 USDC"

A fixed dollar amount. The bot buys or sells exactly this much.

amount = "100 USDC"

When to use: For entries and DCA levels where you want predictable position sizing. Most strategies use fixed amounts for open_long and buy actions.

Supported currencies: USDC, USD, BTC, ETH, and other standard ticker symbols.

Percentage Amount: "50%"

A percentage of either the available balance (for buys) or the current position size (for sells).

amount = "50%"    # Sell half the position
amount = "100%"   # Sell the entire position

When to use:

  • For sell actions: "50%" means sell half your position; "100%" means exit completely.
  • For buy actions: "50%" means use 50% of available balance.

Tip

Use percentage amounts for sells and fixed amounts for buys. This gives you predictable entry sizing while allowing flexible exit sizing. For example, selling "50%" first and then "100%" of the remainder lets you scale out of a position as the price rises.

Amount Format Rules

FormatExampleValid ForDescription
Fixed"100 USDC"open_long, buyBuy exactly 100 USDC worth
Fixed"0.01 BTC"open_long, buyBuy exactly 0.01 BTC
Percentage"50%"buy, sell50% of balance or position
Percentage"100%"sellSell the entire position

Warning

Negative amounts are not allowed. The amount must be a positive number. Use the action type (sell) to indicate selling, not a negative amount.


average_price Explained

The average_price flag controls whether the bot recalculates the position's entry price after a buy or open_long action. This is the core mechanism behind Dollar-Cost Averaging (DCA).

How It Works

When average_price = true and the bot buys more of an asset, the entry price is recalculated as a weighted average:

new_entry_price = (old_qty * old_price + new_qty * new_price) / (old_qty + new_qty)

Example:

  1. You open a position: buy 100 USDC worth of BTC at $50,000. Entry price = $50,000.
  2. Price drops to $48,000. A DCA buy triggers: buy 200 USDC more at $48,000.
  3. With average_price = true, the new entry price becomes:
    • Total cost: $100 + $200 = $300
    • Total BTC: 0.002 + 0.004167 = 0.006167 BTC
    • New entry price: $300 / 0.006167 = $48,649
  4. Now the price only needs to rise to $48,649 (not $50,000) to break even.

When to Use It

Scenarioaverage_priceWhy
DCA buy on diptrueLower your average entry so you break even sooner
Adding to a winnerfalseKeep the original entry price for P&L tracking
Initial open_longfalseNo previous position to average with
All sell actionsfalseSelling does not affect entry price

Note

The average_price flag is only meaningful for open_long and buy actions. Setting it on a sell action has no effect.


Multiple Actions: How They Work Together

A strategy typically has multiple actions -- at least one entry (open_long) and one exit (sell). Here is how they interact:

Evaluation Order

Actions are evaluated independently and in order on every candle:

flowchart TD
    A["Candle Closes"] --> B["Evaluate Action 1<br/>(open_long)"]
    B --> C["Evaluate Action 2<br/>(buy / DCA level 1)"]
    C --> D["Evaluate Action 3<br/>(buy / DCA level 2)"]
    D --> E["Evaluate Action 4<br/>(sell / take profit)"]
    E --> F["Evaluate Action 5<br/>(sell / stop loss)"]

    style A fill:#4a9eff,color:#fff

Key Rules

  1. open_long only fires when no position is open (or when max_open_positions allows another).
  2. buy only fires when a position IS open -- it has nothing to add to otherwise.
  3. sell only fires when a position IS open -- you cannot sell what you do not have.
  4. Multiple sell actions can coexist -- you might have a take-profit sell at +3% AND a stop-loss sell at -8%. Whichever condition is met first will fire.
  5. After a 100% sell, the position is closed -- subsequent buy triggers will not fire until open_long creates a new position.

Typical Action Structure

Most strategies follow this pattern:

# 1. Entry
[[actions]]
type = "open_long"
amount = "100 USDC"
# ... entry triggers ...

# 2. DCA Level 1 (optional)
[[actions]]
type = "buy"
amount = "200 USDC"
average_price = true
# ... dip trigger ...

# 3. DCA Level 2 (optional)
[[actions]]
type = "buy"
amount = "300 USDC"
average_price = true
# ... deeper dip trigger ...

# 4. Take Profit
[[actions]]
type = "sell"
amount = "100%"
# ... profit trigger ...

# 5. Stop Loss
[[actions]]
type = "sell"
amount = "100%"
# ... loss trigger ...

Tip

You can have multiple sell actions with different conditions. For example, sell 50% at +2% profit and the remaining 100% at +5% profit. This lets you scale out of a position gradually.