Advanced Mode

Advanced Mode unlocks the full power of Tradecraft's strategy engine by allowing you to write custom trading strategies in JavaScript. Unlike Easy Mode's visual interface, Advanced Mode gives you complete programmatic control over your trading logic, enabling you to build sophisticated, multi-step strategies that respond to market conditions in real-time.

The syntax of the JavaScript strategy is relatively simple, and barrier to entry for less technical users is low.

What is Advanced Mode?

Advanced Mode is a JavaScript-based strategy editor that provides:

  • Full programming control - Write JavaScript code to define your trading logic

  • Multi-step execution - Create strategies with multiple conditional steps that execute sequentially

  • Real-time data access - Access live price data, historical price ticks and token metadata.

  • Custom indicators - Implement your own technical analysis and custom calculations

  • Strategy state management - Maintain context and variables across strategy executions

  • Debugging capabilities - Set breakpoints, inspect variables, and step through your strategy logic

Why Use Advanced Mode?

Choose Advanced Mode when you need:

  1. Complex conditional logic - Implement sophisticated if/then rules that go beyond simple buy/sell targets

  2. Custom calculations - Calculate your own indicators, moving averages, volatility measures, or trend analysis

  3. Multi-phase strategies - Create strategies with different behavior at different stages (entry, accumulation, exit)

  4. Dynamic position sizing - Calculate buy/sell percentages based on market conditions, not fixed amounts

  5. Token metadata filtering - Filter trades based on token age, creation time, or other properties

  6. Custom risk management - Implement stop-losses, trailing stops, or dynamic risk adjustment

How Strategies Work

Tradecraft strategies are JavaScript classes that define a series of steps. Each step:

  1. Runs sequentially - Steps execute in order from first to last

  2. Receives price data - Steps get the entry price and current price as parameters

  3. Returns a decision - Each step returns whether to buy, sell, stay at the same step or continue to the next step without buying or selling. The decision contains how large part of the position should be bought or sold.

  4. Can access context - Steps can read/write to shared strategy context for state management, to save data that persists over the lifetime of the strategy execution.

Here is a minimal example:

class Strategy {
  constructor() {
    this.strategy = {
      data: {
        token: {
          address: "",
          creationTime: 0
        },
        priceTicks: []
      },
      steps: [
        {
          run: (entry, current) => this.checkBuy(entry, current),
          label: "Buy on 10% dip"
        },
        {
          run: (entry, current) => this.checkSell(entry, current),
          label: "Sell at 2x"
        }
      ],
      context: {}
    }
  }

  checkBuy(entryPrice, currentPrice) {
    // Buy if price drops 10% from entry
    if (currentPrice <= entryPrice * 0.9) {
      return {
        buy: true,
        partToBuyInPercentage: 100
      };
    }
    return { buy: false, partToBuyInPercentage: 0 };
  }

  checkSell(entryPrice, currentPrice) {
    // Sell when price doubles
    if (currentPrice >= entryPrice * 2) {
      return {
        sell: true,
        partToSellInPercentage: 100
      };
    }
    return { sell: false, partToSellInPercentage: 0 };
  }
}

When Strategies Execute

Your strategy code runs continuously on the signals that comes from the connected signal source. The strategy engine executes each step in sequence, passing the entry price (signal price or buy price) and current price to each step's run() function.

In the example, the strategy will wait for a 10% price decrease compared to the price at the signal time. As soon as this occurs, it will open a position and start executing the strategy at it's second step, which sells the whole position at a 100% (2x) price increase.

JavaScript Syntax Reference

This section describes the complete JavaScript syntax specification for Tradecraft strategies.

Class Structure

Every strategy must be a JavaScript class named Strategy with a specific structure:

class Strategy {
  constructor() {
    this.strategy = {
      data: {
        token: {
          address: "",
          creationTime: 0
        },
        priceTicks: []
      },
      steps: [
        // Array of step objects
        run => this.myStep(entry, current)
      ],
      context: {}
    }
  }

  // Your custom step methods here
  myStep(entry, current) {
    // step logic
  }
}

Required Properties

1. this.strategy.data

Contains runtime data automatically injected by the strategy engine:

  • token - Object with token information:

    • address (string) - Token mint address

    • creationTime (number) - Token creation timestamp in milliseconds since epoch

  • priceTicks - Array of price objects:

    • Each tick contains: { usdPrice: number, timestamp: number }

    • Maximum 1000 ticks, in 5 second intervals

    • Ordered with the latest price at the start of the array

    • Example: priceTicks[0] gives the current price

2. this.strategy.steps

Array of step objects that execute sequentially. Each step object has:

  • run (function) - The step execution function

    • Parameters: (entry, current) - MUST be exactly these two parameters

      • entry - Entry price (signal price for first buy, purchase price for sells)

      • current - Current market price

    • Return value: Must return one of the allowed return types (see below)

  • label (string) - Optional descriptive label for the step

Example:

steps: [
  {
    run: (entry, current) => this.checkBuy(entry, current),
    label: "Buy on 10% dip from signal"
  },
  {
    run: (entry, current) => this.checkSell(entry, current),
    label: "Sell at 2x profit"
  }
]

3. this.strategy.context

Object for storing state across strategy executions. Use this for:

  • Tracking highest price for trailing stops

  • Recording when buys/sells occurred

  • Storing custom calculations or flags

Example:

// In a step function:
if (!this.strategy.context.highestPrice) {
  this.strategy.context.highestPrice = current;
} else if (current > this.strategy.context.highestPrice) {
  this.strategy.context.highestPrice = current;
}

Step Function Return Values

Step functions MUST return one of these exact formats:

Buy Action

return {
  buy: true,              // boolean
  partToBuyInPercentage: 100  // number (0-100)
};

Sell Action

return {
  sell: true,              // boolean
  partToSellInPercentage: 50  // number (0-100)
};

Move to Next Step (without buying or selling)

return {
  moveToNextStep: true
};

No Action (stay on current step)

return null;

Important Notes:

  • You CANNOT return anything else besides these four formats

  • Returning null keeps you on the current step for the next price tick

  • Returning moveToNextStep: true advances to the next step permanently - use carefully!

  • Once a step returns buy: true, sell: true, or moveToNextStep: true, that step will NEVER execute again

Common Patterns

Trailing Stops:

// Track highest price in context
if (!context.highestPrice || current > context.highestPrice) {
  context.highestPrice = current;
}

// Sell if drops X% from peak
const dropPercent = (context.highestPrice - current) / context.highestPrice;
if (dropPercent >= 0.15) {
  return { sell: true, partToSellInPercentage: 100 };
}

Time-Based Exits:

// Store entry time in context during buy step
context.entryTime = Date.now();

// In sell step, check elapsed time
const hoursHeld = (Date.now() - context.entryTime) / (1000 * 60 * 60);
if (hoursHeld >= 24 && currentPrice > entryPrice) {
  return { sell: true, partToSellInPercentage: 100 };
}

Last updated