Position Management

Position management is how Botmarley tracks your open trades, controls how many positions can be open at once, and handles adding to or exiting positions. Good position management is often the difference between a profitable strategy and a losing one.

What Is a Position?

A position is an active trade. When a strategy's open_long action fires, Botmarley creates a new position that tracks:

FieldDescription
Entry priceThe price at which the position was opened
QuantityHow much of the asset was bought
Total costThe total USDC (or other currency) spent
Current P&LThe unrealized profit or loss based on current price
Open timeWhen the position was created

A position remains open until a sell action with amount = "100%" fires, or until all of the position has been sold through partial sells.

flowchart LR
    A["open_long<br/>Creates Position"] --> B["Position Open<br/>Tracking P&L"]
    B --> C["buy (DCA)<br/>Adds to Position"]
    C --> B
    B --> D["sell 50%<br/>Partial Exit"]
    D --> B
    B --> E["sell 100%<br/>Full Exit"]
    E --> F["Position Closed"]

    style A fill:#22c55e,color:#fff
    style E fill:#ef4444,color:#fff
    style F fill:#6b7280,color:#fff

max_open_positions

The max_open_positions field in the [meta] section controls how many positions can be open simultaneously. This is your primary tool for controlling capital exposure.

How It Works

[meta]
name = "Conservative Strategy"
max_open_positions = 1
SettingBehavior
max_open_positions = 1Only one position at a time. New open_long triggers are ignored until the current position is fully closed.
max_open_positions = 3Up to three positions can be open simultaneously. The fourth open_long trigger is ignored.
Omitted (no setting)Unlimited positions. Every open_long trigger opens a new position.

Warning

Running with unlimited positions (no max_open_positions) can be dangerous. In a sharp market downturn, the bot could open many positions rapidly, using up all available capital. Always set a limit unless you have a specific reason not to.

Choosing a Limit

StyleRecommendedWhy
Conservative1One trade at a time. Full focus on quality.
Moderate2-3Allows some diversification across entries.
Aggressive5+Many concurrent positions. Higher capital risk.

Example:

[meta]
name = "Single Position Focus"
max_open_positions = 1

# This strategy opens at most one position.
# Even if the entry trigger fires again, no new position is created
# until the current one is fully closed.

DCA -- Dollar-Cost Averaging

DCA is a technique where you buy more of an asset as the price drops, lowering your average entry price. In Botmarley, DCA is implemented using buy actions with average_price = true.

Why Use DCA?

Without DCA, if you buy at $50,000 and the price drops to $48,000, you need the price to return to $50,000 to break even. With DCA, you buy more at $48,000, which lowers your average entry price so you break even at a lower price.

DCA in Practice

Here is how a two-level DCA strategy works:

flowchart TD
    A["open_long: Buy $100 at $50,000<br/>Entry Price = $50,000"] --> B{"Price drops 2%<br/>to $49,000?"}
    B -- "Yes" --> C["buy: Add $200 at $49,000<br/>average_price = true<br/>New Entry = $49,333"]
    B -- "No" --> D{"Price rises 3%<br/>from entry?"}
    C --> E{"Price drops 4%<br/>to $48,000?"}
    E -- "Yes" --> F["buy: Add $300 at $48,000<br/>average_price = true<br/>New Entry = $48,500"]
    E -- "No" --> D
    F --> D
    D -- "Yes" --> G["sell 100%<br/>Take Profit"]

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

Entry Price Recalculation

When average_price = true, the entry price is recalculated as a weighted average:

new_entry_price = total_cost / total_quantity

Step-by-step example:

StepActionPriceAmountTotal CostTotal QtyAvg Entry
1open_long$50,000$100$1000.002 BTC$50,000
2buy (DCA)$49,000$200$3000.006082 BTC$49,327
3buy (DCA)$48,000$300$6000.012332 BTC$48,654

After all three buys, the average entry is $48,654 instead of $50,000. The position needs only a 0% (break-even) to $48,654 recovery instead of a full return to $50,000.

Tip

DCA works best in markets that tend to recover (mean reversion). It can amplify losses in a prolonged downtrend. Always pair DCA with a stop-loss to limit maximum exposure.

max_count for DCA Levels

Use max_count on trigger to limit how many times a DCA level fires per position. Without it, a DCA trigger could fire repeatedly if the price oscillates around the threshold.

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

  [[actions.triggers]]
  type = "pos_price_change"
  value = "-2%"
  max_count = 1        # Only fire once per position

With max_count = 1, this DCA level triggers exactly once. Even if the price bounces above and back below -2%, it will not trigger again for the same position.

Position Tracking

While a position is open, Botmarley continuously tracks:

Entry Price

The price at which the position was opened (or the weighted average if DCA has been applied). This is the reference point for all pos_price_change triggers.

Current P&L (Profit & Loss)

Calculated as:

P&L (%) = (current_price - entry_price) / entry_price * 100

For example, if entry is $48,654 and current price is $50,000:

P&L = (50000 - 48654) / 48654 * 100 = +2.77%

Position Size

The total quantity of the asset held and the total cost basis. This is used by percentage-based sell amounts ("50%" sells half the quantity).

Selling: Partial vs. Full Exit

Partial Sell

Selling less than 100% of the position lets you take some profit while keeping exposure:

# Sell half when profitable
[[actions]]
type = "sell"
amount = "50%"

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

After this sell, 50% of the position remains open. The remaining position continues to be tracked with the same entry price.

Full Exit

Selling 100% closes the position entirely:

# Full exit on profit target
[[actions]]
type = "sell"
amount = "100%"

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

After a full exit, the position is closed. The strategy's open_long action can now create a new position (subject to max_open_positions).

Scaling Out

You can combine multiple sell actions to scale out of a position gradually:

# Sell 30% at +2%
[[actions]]
type = "sell"
amount = "30%"

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

# Sell 50% at +4%
[[actions]]
type = "sell"
amount = "50%"

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

# Sell remaining 100% at +6%
[[actions]]
type = "sell"
amount = "100%"

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

Note

Percentage sells are relative to the current position size, not the original. If you sell 50% and then 50% again, you have sold 75% of the original position (50% + 50% of the remaining 50%).

Complete DCA Strategy Example

Here is a full strategy that demonstrates position management in action -- it enters on a Bollinger Band touch, DCA buys at -2%, -4%, and -6%, and exits at +3% profit or -10% stop-loss:

[meta]
name = "BB DCA with Stop Loss"
description = "Bollinger Band entry, 3-level DCA, profit target, and hard stop-loss"
max_open_positions = 1

# ENTRY: Price touches lower Bollinger Band
[[actions]]
type = "open_long"
amount = "100 USDC"
average_price = false

  [[actions.triggers]]
  indicator = "price"
  operator = "<"
  target = "bb_lower"
  timeframe = "1h"

# DCA LEVEL 1: Buy more at -2% from entry
[[actions]]
type = "buy"
amount = "100 USDC"
average_price = true

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

# DCA LEVEL 2: Buy more at -4% from entry
[[actions]]
type = "buy"
amount = "200 USDC"
average_price = true

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

# DCA LEVEL 3: Buy more at -6% from entry
[[actions]]
type = "buy"
amount = "300 USDC"
average_price = true

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

# TAKE PROFIT: Sell everything at +3%
[[actions]]
type = "sell"
amount = "100%"

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

# STOP LOSS: Cut losses at -10%
[[actions]]
type = "sell"
amount = "100%"

  [[actions.triggers]]
  type = "pos_price_change"
  value = "-10%"

How this plays out:

  1. Price drops below the lower Bollinger Band on the 1h chart -- the bot buys $100.
  2. If price continues dropping 2% from entry, the bot buys another $100 and averages the entry price down.
  3. If it drops 4% from entry, another $200 is added. At 6%, another $300.
  4. Maximum total investment: $100 + $100 + $200 + $300 = $700.
  5. If price recovers 3% from the (averaged) entry price, everything is sold for profit.
  6. If price drops 10% from entry without recovery, the stop-loss fires and cuts losses.

Tip

Notice the increasing DCA amounts ($100, $100, $200, $300). This is called pyramid DCA -- you invest more at lower prices where the risk-reward is better. The largest buy happens at the deepest dip.