Mastering Pump.fun with WebSocket: A Tutorial on Trailing Stop-Loss Strategies

Mastering Pump.fun with WebSocket: A Tutorial on Trailing Stop-Loss Strategies

Alright, crypto warriors!
Welcome back to the Pump.Fun Trading Bot series. If you're here, you're ready to take your trading bot to the next level and conquer the crypto battlefield with advanced automation techniques. Buckle up because we’re diving into building smarter logic for maximizing profits while minimizing risks.

If you missed the basics—like WebSocket connection setup or account registration make sure to check out Mastering Pump.fun trade with WebSocket Series 1 to get started.

So What Are We Building Today?

We're building an advanced trading bot for the pump.fun platform that utilizes WebSocket technology to monitor peak prices in real time. The bot will continuously track new coins and market transactions, comparing these peak prices to a predefined trailing price. Based on this comparison, it will make intelligent decisions on when to sell the coins, aiming to maximize profits by identifying optimal selling points. With smart stop-loss mechanisms in place, this bot will help you navigate the market, ensuring you stay ahead in the fast-paced world of crypto trading!

What is the Trailing Price?

The trailing price represents a fixed difference between the peak price (the highest price reached) and the trade price. It adjusts dynamically with the market price, always maintaining a specific distance below the peak.

How do we utilize Trailing Price?

When a transaction occurs, the program calculates the difference between the peak price and the current trade price. This difference is then compared to the set trailing price. If the difference exceeds the trailing price, a sell condition is triggered.

Example:

Let’s say the trade price fluctuates as follows: 10, 11, 12, 13 ... 15, 16, 17.5, 16, 15, and so on.

  • The peak price is 17.5, and the trailing price is set at 2.
  • As the trade price changes, the program continuously checks the difference between the peak price and the current trade price.

When the trade price drops to 15, the difference between the peak price (17.5) and the current price (15) becomes:
17.5 - 15 = 2.5, which exceeds the set trailing price (2).

At this point, the trailing stop is triggered, and a sell notification is sent.

Let's Get Started

Prerequisites

Make sure you have the following before we dive in:

  • Python (Version 3.x+ recommended).
  • A registered account on nolimitnodes.com to get your free API key.

Let's Get Codin'

Open your favorite IDE (I use PyCharm). Create a new script called trading_bot_pumpfun.py

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

import websocket
import json
import threading

Now, let’s define some key variables that set the foundation for our bot’s trading strategy. These variables establish the initial conditions for trading:

  • buy_price: The price at which you decide to purchase a coin.
  • takeProfit_price: The target price at which you plan to sell to lock in profits.
  • trailing_amount: The threshold amount below the peak price. If the coin’s price falls below this level, it triggers a sell condition to minimize potential losses or secure profits.
# Constants
BUY_PRICE = 0.0000001000
TAKE_PROFIT_PRICE = 0.0000001500
TRAILING_AMT = 0.0000000200
STOP_LOSS_PRICE = 0.0000000800
buy_trade = 0
profit_trade = 0
loss_trade = 0

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

Next, we send a request to the server to get the crypto data we need.

# Subscription messages
SUBSCRIBE_NEW_COIN = {
    "method": "pumpFunCreateEventSubscribe",
    "params": {"eventType": "coin", "referenceId": "hello"}
}

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


Now, let’s set up some efficient storage for tracking our potential opportunities:


# Data storage
buy_dict = {}
sell_dict = {}

It’s time to unleash the real magic! These functions will turn your bot into a powerhouse, smarter than any team of crypto analysts.

Trading Logic:

  • When a transaction has a coin in the Buylist:
    • If the coin’s price exceeds the Buy_price and is less then the TakeProfit_Price set a notification to buy the coin. The coin is then moved from the Buylist to the Selllist, and the peak price is stored.
  • When a transaction has a coin in the Selllist:
    • If the transaction price exceeds the stored peak price, the peak price is updated.
    • If the coin’s price exceeds the TakeProfit_Price or drops below the peak price by trailing_amount, set a notification to sell the coin. The coin is then removed from the Selllist.
def handle_new_coin_message(ws, message):
    global buy_dict
    data = json.loads(message)
    if data.get("method") == "createEventNotification":
        coin_details = data["result"]
        coin_mint = coin_details["mint"]
        # print(f"coin added {coin_details['symbol']}")
        if (coin_mint not in buy_dict):
            buy_dict[coin_mint] = {
                "name": coin_details["name"],
                "symbol": coin_details["symbol"]
            }

def handle_transaction_message(ws, message):
    global buy_trade, profit_trade, loss_trade, buy_dict, sell_dict
    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 Buy Condition
        if  ((trade_token_out in buy_dict) and (trade_price >= BUY_PRICE) and (trade_price <TAKE_PROFIT_PRICE)):
            coin = buy_dict.pop(trade_token_out)
            coin["peak_price"] = trade_price
            sell_dict[trade_token_out] = coin
            buy_trade += 1

            print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# BUY  - Condition met         : [{coin['symbol']}] at price [{trade_price:.10f}] (Address: {trade_token_out})")

        # Handle Sell Conditions
        elif (trade_token_out in sell_dict):
            coin = sell_dict[trade_token_out]
            if (trade_price > coin.get("peak_price", 0)):
                coin["peak_price"] = trade_price

            peak_price = coin["peak_price"]
            peak_diff = (peak_price - trade_price)
            if ((trade_price >= TAKE_PROFIT_PRICE) or (TRAILING_AMT < peak_diff)):
                if trade_price >= BUY_PRICE:
                    profit_trade += 1
                else:
                    loss_trade += 1
                reason = "Target Achieved       :" if (trade_price >= TAKE_PROFIT_PRICE) else "Trailing threshold Met:"
                print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# SELL - {reason} [{coin['symbol']}] at price [{trade_price:.10f}] (Address: {trade_token_out})")
                del sell_dict[trade_token_out]
            elif (trade_price < STOP_LOSS_PRICE):
                loss_trade += 1
                print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# SELL - Stop loss triggered   : [{coin['symbol']}] at price [{trade_price:.10f}] (Address: {trade_token_out})")
                del sell_dict[trade_token_out]

Finally, let’s create a function to manage our WebSocket connections, and we’ll leverage threading to handle multiple WebSockets simultaneously. It’s like having a whole squad of crypto ninjas working for you around the clock!


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

# Threads for WebSocket connections
thread_new_coin = threading.Thread(target=run_websocket, args=(URL, handle_new_coin_message, SUBSCRIBE_NEW_COIN))
thread_transaction = threading.Thread(target=run_websocket, args=(URL, handle_transaction_message, SUBSCRIBE_PUMP_FUN_TRADE))

thread_new_coin.start()
thread_transaction.start()

thread_new_coin.join()
thread_transaction.join()

Bringing It All Together

import websocket
import json
import threading

# Constants
BUY_PRICE = 0.0000001000
TAKE_PROFIT_PRICE = 0.0000001500
TRAILING_AMT = 0.0000000200
STOP_LOSS_PRICE = 0.0000000800
buy_trade = 0
profit_trade = 0
loss_trade = 0

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

# Subscription messages
SUBSCRIBE_NEW_COIN = {
    "method": "pumpFunCreateEventSubscribe",
    "params": {"eventType": "coin", "referenceId": "hello"}
}

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

# Data storage
buy_dict = {}
sell_dict = {}

# WebSocket Handlers
def handle_new_coin_message(ws, message):
    global buy_dict
    data = json.loads(message)
    if data.get("method") == "createEventNotification":
        coin_details = data["result"]
        coin_mint = coin_details["mint"]
        # print(f"coin added {coin_details['symbol']}")
        if coin_mint not in buy_dict:
            buy_dict[coin_mint] = {
                "name": coin_details["name"],
                "symbol": coin_details["symbol"]
            }

def handle_transaction_message(ws, message):
    global buy_trade, profit_trade, loss_trade, buy_dict, sell_dict
    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 Buy Condition
        if trade_token_out in buy_dict and trade_price >= BUY_PRICE:
            coin = buy_dict.pop(trade_token_out)
            coin["peak_price"] = trade_price
            sell_dict[trade_token_out] = coin
            buy_trade += 1

            print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# BUY  - Condition met         : [{coin['symbol']}] at price [{trade_price:.10f}] (Address: {trade_token_out})")

        # Handle Sell Conditions
        elif trade_token_out in sell_dict:
            coin = sell_dict[trade_token_out]
            if trade_price > coin.get("peak_price", 0):
                coin["peak_price"] = trade_price

            peak_price = coin["peak_price"]
            peak_diff = peak_price - trade_price
            if trade_price >= TAKE_PROFIT_PRICE or TRAILING_AMT < peak_diff:
                if trade_price >= BUY_PRICE:
                    profit_trade += 1
                else:
                    loss_trade += 1
                reason = "Target Achieved       :" if trade_price >= TAKE_PROFIT_PRICE else "Trailing threshold Met:"
                print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# SELL - {reason} [{coin['symbol']}] at price [{trade_price:.10f}] (Address: {trade_token_out})")
                del sell_dict[trade_token_out]
            elif trade_price < STOP_LOSS_PRICE:
                loss_trade += 1
                print(f"#Bought:{buy_trade}#Profit:{profit_trade}#Loss:{loss_trade}# SELL - Stop loss triggered   : [{coin['symbol']}] at price [{trade_price:.10f}] (Address: {trade_token_out})")
                del sell_dict[trade_token_out]

def on_error(ws, error):
    print(f"Error: {error}")

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

def on_open(ws, subscription_message):
    print("WebSocket connection opened")
    ws.send(json.dumps(subscription_message))
    print(f"Subscription message sent: {subscription_message}")

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

# Threads for WebSocket connections
thread_new_coin = threading.Thread(target=run_websocket, args=(URL, handle_new_coin_message, SUBSCRIBE_NEW_COIN))
thread_transaction = threading.Thread(target=run_websocket, args=(URL, handle_transaction_message, SUBSCRIBE_PUMP_FUN_TRADE))

thread_new_coin.start()
thread_transaction.start()

thread_new_coin.join()
thread_transaction.join()


Wrapping It Up

And there you have it, crypto commandos! You’ve built a powerful trading bot that’s ready to dominate the pump.fun world. This bot will monitor new coins, compare their peak-price to a predefined trailing price, and make trading decisions accordingly. It will buy low when conditions are met and sell high when your take-profit or stop-loss triggers activate. With this bot by your side, you’ll be:

  • Collecting new coins
  • Tracking peak prices and trailing prices to make informed trades
  • Seizing opportunities by purchasing at the right time and maximizing profits through smart selling.

With a smart stop-loss mechanism, the bot helps you navigate the market effectively, ensuring you stay ahead in the dynamic world of crypto trading.

Use it wisely, and may your profits grow steadily! Happy trading, and may your success continue to soar.

For more information on the other pump.fun APIs, check out https://nolimitnodes.com/blog/pump-fun-websocket-build-a-real-time-crypto-trading-bot-with-nolimitnodes-price-data/ 

If you're facing any issues or need help with crypto-related topics, feel free to reach out! Drop me an email at robert.king@nolimitnodes.com, and I'll respond as soon as I can—usually within 24 hours.