Pump.fun WebSocket Tutorial: Master Drawdown Strategies for Maximizing Pullback Gains

Hello, crypto warriors!
Welcome back to the Pump.Fun Trading Bot series! If you're here, it means you're ready to elevate your trading bot skills and dominate the crypto market with cutting-edge automation strategies. Get ready, because we’re about to explore advanced logic for maximizing profits while managing risks effectively.

If you’re new or missed the fundamentals—like setting up WebSocket connections or registering an account—make sure to check out Mastering Pump.Fun Trading with WebSocket: Series 1 to get up to speed.

So What Are We Building Today?

We're building an intelligent drawdown trading bot for the Pump.fun platform, leveraging WebSocket technology to monitor live market transactions and token prices in real time. The bot will track peak prices, detect drawdowns, and calculate pullback percentages to identify the perfect opportunities for buying. With automated stop-loss and profit-taking strategies, it will decide the optimal moments to sell, maximizing gains while minimizing losses. This bot is designed to streamline trading, letting you capitalize on market movements without constant manual intervention—helping you stay ahead in the dynamic world of cryptocurrency trading!

What is Drawdown Trading?

Drawdown trading is a strategy used by traders to monitor and react to price fluctuations in assets. A drawdown represents the decline in the price of an asset from its peak to a trough, often measured as a percentage. Traders use this metric to identify buying opportunities during price dips (drawdowns) and selling opportunities when the price recovers or pulls back.

For example, if a cryptocurrency or stock falls by 10% from its peak and then starts recovering, a trader might buy at the trough and sell when it rises by a specific percentage (profit target). Drawdown trading can also involve setting stop-loss levels to minimize losses when the asset's price drops below a threshold.

How Does a Drawdown Trading Bot Work?

A drawdown trading bot automates the process of tracking asset prices, identifying drawdowns, and executing buy or sell decisions. Here's how it works:

  1. Track Price Peaks: The bot monitors the market in real-time and records the peak prices of assets.
  2. Identify Drawdowns: When the price drops by a defined percentage from the peak, the bot recognizes this as a drawdown.
  3. Trigger a Pullback Buy: If the price starts recovering and exceeds a set percentage from the trough, the bot triggers a buy.
  4. Sell on Profit or Stop Loss: After buying, the bot tracks the price to either sell at a profit percentage or cut losses with a stop-loss mechanism.

Example:

  • Peak Price Tracking:
    The price of Token A rises to $100 and is recorded as the peak.
  • Drawdown Detected:
    The price drops to $90 (10% drop). The bot identifies this as a drawdown and sets $90 as the trough price.
  • Pullback Buy Triggered:
    The price recovers to $94.50 (5% pullback). The bot buys Token A at $94.50.
  • Profit or Stop Loss:If the price rises to $99.23 (5% profit), the bot sells for a profit.If the price falls to $92.61 (2% loss), the bot sells to minimize losses.

Let's build a bot

Prerequisites

Before we get started, ensure you have the following:

  • Python (Version 3.x or higher is recommended).
  • A registered account on nolimitnodes.com to obtain your free API key.

Open your favorite IDE and create a new script named drawdown_bot_pumpfun.py

To get started, we’ll import the essential libraries that will empower our trading bot:

import websocket
import json
import threading

Global Variables

The bot uses several variables to configure trading parameters:

  • DRAW_DOWN_TRACE_PRICE : Minimum price above which tokens are monitored.
  • DRAW_DOWN_PERCENT : Percentage drop from the peak price to define a drawdown.
  • DRAW_DOWN_PULLBACK_PERCENT : Recovery percentage from the trough to trigger a buy.
  • PROFIT_PERCENT and STOP_LOSS_PERCENT : Conditions for selling after a buy.

Data Structures

  • draw_down_dict: Stores information about tokens being tracked for drawdown.
  • sell_dict: Keeps track of tokens that have been bought and are being monitored for selling.
# Define constants
DRAW_DOWN_TRACK_PRICE = 0.0000001000
DRAW_DOWN_PERCENT = 10.0 / 100.0
DRAW_DOWN_PULLBACK_PERCENT = 5.0 / 100.0
PROFIT_PERCENT = 10.0 / 100.0
STOP_LOSS_PERCENT = 5.0 / 100.0

# Data storage
draw_down_dict = {}
sell_dict = {}
buy_trade = profit_trade = loss_trade = 0


URL = "wss://api.nolimitnodes.com/pump-fun?api_key=YOUR_API_KEY"

Next, we make a request to the server to fetch the required cryptocurrency data.

# Subscription messages
SUBSCRIBE_PUMP_FUN_TRADE = {
    "method": "pumpFunTradeSubscribe",
    "params": {"referenceId": "hello", "coinAddress": "all"}
}


It’s time to unlock the real potential! These functions will transform your bot into a powerhouse, outsmarting even the best crypto analysts.

Code Breakdown and Logic:

The bot evaluates every trade event using the following logic:

  • Track Tokens with Drawdown Potential:
    If a token's price exceeds DRAW_DOWN_TRACE_PRICE and it's not in draw_down_dict the bot starts monitoring it.
  • Update Peak Prices:
    If the price rises further, the peak price for the token is updated.
  • Identify Drawdowns:
    If the price falls below the peak, the bot calculates the drawdown percentage. If it exceeds DRAW_DOWN_PERCENT , the trough price is recorded.
  • Trigger Pullback Buys:
    If the price recovers by DRAW_DOWN_PULLBACK_PERCENT from the trough, the bot triggers a buy and moves the token to sell_dict.
  • Monitor for Profit or Stop Loss:
    Tokens in sell_dict are sold if they meet the PROFIT_PERCENT or fall below the STOP_LOSS_PERCENT .
# Helper Functions
def handle_new_token(trade_token_out, trade_price):
    if trade_token_out not in draw_down_dict and trade_price >= DRAW_DOWN_TRACK_PRICE:
        draw_down_dict[trade_token_out] = {
            "DrawDownPeakPrice": trade_price,
            "DrawDownBottomPrice": None,
            "BuyPrice": None,
        }

def handle_peak_price_update(trade_token_out, trade_price):
    if trade_token_out in draw_down_dict:
        current_data = draw_down_dict[trade_token_out]
        if trade_price > current_data["DrawDownPeakPrice"] and current_data["DrawDownBottomPrice"] is None:
            current_data["DrawDownPeakPrice"] = trade_price

def handle_price_fall(trade_token_out, trade_price):
    if trade_token_out in draw_down_dict:
        current_data = draw_down_dict[trade_token_out]
        peak_price = current_data["DrawDownPeakPrice"]
        
        if trade_price < peak_price:
            fall_percentage = (peak_price - trade_price) / peak_price
            if fall_percentage >= DRAW_DOWN_PERCENT:
                bottom_trade_price = current_data.get("DrawDownBottomPrice")
                if bottom_trade_price is None or bottom_trade_price > trade_price:
                    current_data["DrawDownBottomPrice"] = trade_price

def handle_pullback_and_buy(trade_token_out, trade_price):
    global buy_trade, sell_dict
    if trade_token_out in draw_down_dict:
        current_data = draw_down_dict[trade_token_out]
        bottom_price = current_data["DrawDownBottomPrice"]
        
        if bottom_price is not None and trade_price > bottom_price:
            pullback_percentage = (trade_price - bottom_price) / bottom_price
            if pullback_percentage >= DRAW_DOWN_PULLBACK_PERCENT:
                current_data["BuyPrice"] = trade_price
                sell_dict[trade_token_out] = draw_down_dict.pop(trade_token_out)
                buy_trade += 1
                print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# BUY - Condition met: Trade_price [{trade_price:.10f}], Peak_price [{current_data['DrawDownPeakPrice']:.10f}], Bottom_price [{bottom_price:.10f}], (Address: {trade_token_out})")

def handle_sell_conditions(trade_token_out, trade_price):
    global profit_trade, loss_trade, sell_dict
    if trade_token_out in sell_dict:
        sell_data = sell_dict[trade_token_out]
        buy_price = sell_data["BuyPrice"]
        bottom_price = sell_data["DrawDownBottomPrice"]
        peak_price = sell_data["DrawDownPeakPrice"]
        
        profit_threshold = buy_price * (1 + PROFIT_PERCENT)
        loss_threshold = buy_price * (1 - STOP_LOSS_PERCENT)

        if trade_price >= profit_threshold:
            profit_trade += 1
            print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# SELL - Target Achieved: Trade_price [{trade_price:.10f}], Peak_price [{peak_price:.10f}], Buy_price [{buy_price:.10f}], Bottom_price [{bottom_price:.10f}], (Address: {trade_token_out})")
            sell_dict.pop(trade_token_out)

        elif trade_price <= loss_threshold:
            loss_trade += 1
            print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# SELL - Stop loss triggered: Trade_price [{trade_price:.10f}], Peak_price [{peak_price:.10f}], Buy_price [{buy_price:.10f}], Bottom_price [{bottom_price:.10f}], (Address: {trade_token_out})")
            sell_dict.pop(trade_token_out)

# Main Function to handle transaction messages
def handle_transaction_message(ws, message):
    try:
        data = json.loads(message)
        if data.get("method") == "tradeEventNotification":
            trade_details = data["result"]
            trade_token_out = trade_details["token_out"]["token"]
            trade_price = float(trade_details["price"]["sol"])

            handle_new_token(trade_token_out, trade_price)
            handle_peak_price_update(trade_token_out, trade_price)
            handle_price_fall(trade_token_out, trade_price)
            handle_pullback_and_buy(trade_token_out, trade_price)
            handle_sell_conditions(trade_token_out, trade_price)

    except json.JSONDecodeError as e:
        print(f"[ERROR] JSON Decode Error: {e}")
    except Exception as e:
        print(f"[ERROR] Exception occurred: {e}")

Finally, let's build a function to manage our WebSocket connections, using threading to handle multiple connections simultaneously. It’s like having a team of crypto experts working tirelessly for you, around the clock!


# Function to create and run a WebSocket connection
def run_websocket():
    ws = websocket.WebSocketApp(
        URL,
        on_message=handle_transaction_message,
        on_error=on_error,
        on_close=on_close
    )
    ws.on_open = on_open
    ws.run_forever()

# Start WebSocket in a thread
thread_transaction = threading.Thread(target=run_websocket)
thread_transaction.start()
thread_transaction.join()

Bringing It All Together

import websocket
import json
import threading

# Define constants
DRAW_DOWN_TRACK_PRICE = 0.0000001000
DRAW_DOWN_PERCENT = 10.0 / 100.0
DRAW_DOWN_PULLBACK_PERCENT = 5.0 / 100.0
PROFIT_PERCENT = 10.0 / 100.0
STOP_LOSS_PERCENT = 5.0 / 100.0

# Data storage
draw_down_dict = {}
sell_dict = {}
buy_trade = profit_trade = loss_trade = 0

# WebSocket URL
URL = "wss://api.nolimitnodes.com/pump-fun?api_key=YOUR_API_KEY"

# Subscription message
SUBSCRIBE_PUMP_FUN_TRADE = {
    "method": "pumpFunTradeSubscribe",
    "params": {"referenceId": "hello", "coinAddress": "all"}
}

# Helper Functions
def handle_new_token(trade_token_out, trade_price):
    if trade_token_out not in draw_down_dict and trade_price >= DRAW_DOWN_TRACK_PRICE:
        draw_down_dict[trade_token_out] = {
            "DrawDownPeakPrice": trade_price,
            "DrawDownBottomPrice": None,
            "BuyPrice": None,
        }

def handle_peak_price_update(trade_token_out, trade_price):
    if trade_token_out in draw_down_dict:
        current_data = draw_down_dict[trade_token_out]
        if trade_price > current_data["DrawDownPeakPrice"] and current_data["DrawDownBottomPrice"] is None:
            current_data["DrawDownPeakPrice"] = trade_price

def handle_price_fall(trade_token_out, trade_price):
    if trade_token_out in draw_down_dict:
        current_data = draw_down_dict[trade_token_out]
        peak_price = current_data["DrawDownPeakPrice"]
        
        if trade_price < peak_price:
            fall_percentage = (peak_price - trade_price) / peak_price
            if fall_percentage >= DRAW_DOWN_PERCENT:
                bottom_trade_price = current_data.get("DrawDownBottomPrice")
                if bottom_trade_price is None or bottom_trade_price > trade_price:
                    current_data["DrawDownBottomPrice"] = trade_price

def handle_pullback_and_buy(trade_token_out, trade_price):
    global buy_trade, sell_dict
    if trade_token_out in draw_down_dict:
        current_data = draw_down_dict[trade_token_out]
        bottom_price = current_data["DrawDownBottomPrice"]
        
        if bottom_price is not None and trade_price > bottom_price:
            pullback_percentage = (trade_price - bottom_price) / bottom_price
            if pullback_percentage >= DRAW_DOWN_PULLBACK_PERCENT:
                current_data["BuyPrice"] = trade_price
                sell_dict[trade_token_out] = draw_down_dict.pop(trade_token_out)
                buy_trade += 1
                print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# BUY - Condition met: Trade_price [{trade_price:.10f}], Peak_price [{current_data['DrawDownPeakPrice']:.10f}], Bottom_price [{bottom_price:.10f}], (Address: {trade_token_out})")

def handle_sell_conditions(trade_token_out, trade_price):
    global profit_trade, loss_trade, sell_dict
    if trade_token_out in sell_dict:
        sell_data = sell_dict[trade_token_out]
        buy_price = sell_data["BuyPrice"]
        bottom_price = sell_data["DrawDownBottomPrice"]
        peak_price = sell_data["DrawDownPeakPrice"]
        
        profit_threshold = buy_price * (1 + PROFIT_PERCENT)
        loss_threshold = buy_price * (1 - STOP_LOSS_PERCENT)

        if trade_price >= profit_threshold:
            profit_trade += 1
            print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# SELL - Target Achieved: Trade_price [{trade_price:.10f}], Peak_price [{peak_price:.10f}], Buy_price [{buy_price:.10f}], Bottom_price [{bottom_price:.10f}], (Address: {trade_token_out})")
            sell_dict.pop(trade_token_out)

        elif trade_price <= loss_threshold:
            loss_trade += 1
            print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# SELL - Stop loss triggered: Trade_price [{trade_price:.10f}], Peak_price [{peak_price:.10f}], Buy_price [{buy_price:.10f}], Bottom_price [{bottom_price:.10f}], (Address: {trade_token_out})")
            sell_dict.pop(trade_token_out)

# Main Function to handle transaction messages
def handle_transaction_message(ws, message):
    try:
        data = json.loads(message)
        if data.get("method") == "tradeEventNotification":
            trade_details = data["result"]
            trade_token_out = trade_details["token_out"]["token"]
            trade_price = float(trade_details["price"]["sol"])

            handle_new_token(trade_token_out, trade_price)
            handle_peak_price_update(trade_token_out, trade_price)
            handle_price_fall(trade_token_out, trade_price)
            handle_pullback_and_buy(trade_token_out, trade_price)
            handle_sell_conditions(trade_token_out, trade_price)

    except json.JSONDecodeError as e:
        print(f"[ERROR] JSON Decode Error: {e}")
    except Exception as e:
        print(f"[ERROR] Exception occurred: {e}")

# WebSocket callbacks
def on_error(ws, error):
    print(f"[ERROR] WebSocket Error: {error}")

def on_close(ws, close_status_code, close_msg):
    print("[INFO] WebSocket closed")

def on_open(ws):
    print("[INFO] WebSocket connection opened")
    ws.send(json.dumps(SUBSCRIBE_PUMP_FUN_TRADE))

# Function to create and run a WebSocket connection
def run_websocket():
    ws = websocket.WebSocketApp(
        URL,
        on_message=handle_transaction_message,
        on_error=on_error,
        on_close=on_close
    )
    ws.on_open = on_open
    ws.run_forever()

# Start WebSocket in a thread
thread_transaction = threading.Thread(target=run_websocket)
thread_transaction.start()
thread_transaction.join()

Finally!

You’ve built a powerful trading bot to monitor live market prices, track pullbacks, and make calculated buy and sell decisions. With this bot, you can seize optimal buying opportunities, maximize profits, and protect your investments with smart stop-loss strategies. Now, trade smarter and watch your success unfold in the fast-paced crypto world!

Did you miss Series 2 (the powerful bot that tracks and monitors trailing prices with precision)? No worries! Simply click on Mastering Pump.Fun Trading with WebSocket: Series 2 to catch up and start using your ultimate trading companion today!

To explore more of the pump.fun APIs, visit https://nolimitnodes.com/blog/pump-fun-websocket-build-a-real-time-crypto-trading-bot-with-nolimitnodes-price-data/.

If you run into any issues or need general advice on anything crypto-related, feel free to reach out. You can email me at robert.king@nolimitnodes.com, and I typically check my email once a day.

-Happy Trading!