YouMind
Войти

Grok Bot с нуля за одну ночь: полная настройка + фильтр для защиты от скама (copy-paste)

@0xboan
АНГЛИЙСКИЙ17 окт. 2026 г.
126K
139
19
20
439

Суть

В этом руководстве подробно описано создание торгового терминала Grok Bot с нуля, с акцентом на строгий 14-этапный фильтр для исключения мошеннических токенов перед исполнением сделок. Особое внимание уделяется рабочему процессу «код выполняет, Grok анализирует, вы подтверждаете» с использованием механизмов бумажной торговли.

большинство людей знакомятся с Grok Bot через чужой скриншот pnl, открывают его, наводят на график и теряют первые $50 на токене, который умер еще до того, как они его купили. проблема была не в боте. ему просто никто не объяснил, как выглядит смерть.

вот сетап, который я бы собрал заново сегодня вечером, если бы пришлось начинать с нуля. один бот, одна папка, десять небольших файлов. он не охотится за 100x. его главная задача — убивать токены, а те немногие, что выживают, всё равно требуют, чтобы Grok прочитал X, прежде чем сдвинется хоть один доллар.

шаги с 01 по 07 — это первый вечер: бот, ключ, лимиты, выходы. с 08 по 12 — фильтр рагпулов, 14 проверок, каждая из которых прописана кодом. 13 и 14 переводят всё на автопилот, сначала только на бумаге.

если вы читали мой пост про стол на восемь агентов, то вот тот фундамент, на котором этот стол стоит.

https://x.com/0xboan/status/2092226208234647626

как этим пользоваться: откройте свой Grok Bot, вставьте всю эту статью целиком и скажите «собери этот стол в /workspace/desk, режим paper mode, спрашивай меня, прежде чем что-то коснется кошелька». он сам напишет каждый файл на своем собственном компьютере.

разделение, которого нужно придерживаться: код убивает, Grok читает X, ты подписываешь. никто за столом не делает чужую работу.

01. подготовь четыре вещи до начала

четыре вещи. для каждой указано, что это, что с ней делать сегодня вечером и зачем она нужна столу.

1. Grok Bot

что это. приложение, где ты нанимаешь именных ботов. каждый работает на облачном компьютере с браузером, файлами и терминалом, и продолжает работать, даже когда твой ноутбук закрыт.

что делать. скачай на x.ai/bot, войди, выбери Create your own.

зачем. весь стол живет на этом компьютере. файлы, рутины, алерты — всё в одном месте, которое можно открыть с телефона.

2. API-ключ xAI

что это. платный доступ к Grok из кода со встроенным поиском по X.

что делать. console.x.ai, API Keys, создай один. пока никуда его не вставляй, в шаге 03 сказано, куда он идет.

зачем. рутина не может сидеть и размышлять о сорока токенах в чате. скрипт, делающий один вызов на токен, может, и он логирует каждый ответ в одном формате.

3. Rugcheck и DexScreener

что это. два бесплатных публичных API. Rugcheck читает контракт: права (authorities), LP, холдеров, инсайдеров, кошелек дева. DexScreener читает пул: глубину, возраст, покупки против продаж.

что делать. ничего. никакой регистрации, никаких ключей для чтения.

зачем. факты идут раньше мнений. открытый mint authority — это не вопрос оценки, это факт, а факты убивают первыми.

4. одноразовый кошелек, но не сегодня

что это. свежий Solana-кошелек, на котором никогда ничего не лежало.

что делать. пока ничего. первая неделя проходит на бумаге.

зачем. стол никогда не хранит ключ. когда перейдешь в лайв, он скажет тебе, что покупать, а подпишешь ты сам.

02. найми одного бота, а не восьмерых

мой стол сейчас гоняет восемь ботов. так было не с самого начала, и у тебя не должно быть. восемь ботов в первый день — это восемь вещей, которые придется дебажить одновременно. один бот с одной задачей покажет, что понадобится остальным семерым позже.

выбери Create your own и дай ему это, слово в слово:

text
1Имя: RUG DESK
2Задача: торговый стол для Solana-мемкоинов, сначала на бумаге
3Описание: Собери и запусти стол в /workspace/desk по статье, которую я вставлю.
4Каждый токен проходит через check.py, без исключений и коротких путей.
5Ты никогда не покупаешь, не продаешь, не подписываешь и не перемещаешь средства. Ты никогда не редактируешь config.py, если я не попрошу
6в этом чате. Ты никогда не занижаешь параметры фильтров, чтобы пропустить токен.
7Сообщай о каждом убийстве с указанием причины, а не своего мнения о токене.
8Если источник упал, скажи какой именно и пропусти. Никогда не угадывай недостающее число.

последние две строки важнее первых пяти. бот, который угадывает недостающие числа, рано или поздно угадает то, что будет стоить тебе денег.

boan - inline image

03. держи ключ подальше от чата

всё, что ты пишешь боту, попадает в лог чата. поэтому ключ отправляется в файл, который ты набираешь вручную на компьютере бота.

открой компьютер бота, нажми Take over, открой терминал и выполни это. команда запросит ключ без вывода символов на экран, так что он не попадет и в историю:

bash
1mkdir -p /workspace/desk && cd /workspace/desk
2read -rs -p "xai key: " K && printf 'XAI_API_KEY=%s\n' "$K" > .env && unset K
3chmod 600 .env
4pip install requests

затем убедись, что ключ работает, прежде чем делать что-то еще. один вызов, чтобы потом никогда не путать плохой ключ с плохим промптом:

bash
1curl -s https://api.x.ai/v1/responses \
2 -H "Authorization: Bearer $(cut -d= -f2 .env)" \
3 -H "Content-Type: application/json" \
4 -d '{"model":"grok-4.7","input":"reply with OK"}'
5
6-> ... "type":"output_text","text":"OK" ...

нажми I'm done и верни управление компьютером. с этого момента бот может управлять столом, и при этом он всё равно никогда не увидит ключ в чате.

boan - inline image

04. посмотри на всю воронку до того, как начнешь её строить

восемь проходов. бесплатные запускаются первыми. только то, что переживет бесплатные проверки, стоит вызова Grok, и только то, чему Grok скажет BUY, стоит денег. на этой неделе — даже не это.

text
10. ЛИД CA откуда угодно: звонок, пост, scan.py -> один минт
21. ЛИМИТЫ book.py: дневной убыток, открытые слоты, кулдаун -> бесплатно, вообще без сети
32. ФАКТЫ rugcheck.py: 10 жестких убийств -> открытый минт, разблокированный LP, жирный топ-10 умирают здесь
43. ПУЛ market.py: глубина, возраст, продажи -> тонкие пулы и ханипоты умирают здесь
54. СУДЬЯ grok.py + поиск по X, один вызов -> BUY или SKIP, одна причина, один риск
65. ИСПОЛНЕНИЕ бумага: book.py по живой цене -> лайв: ты подписываешь сам
76. НАБЛЮДЕНИЕ watch.py каждые 10 минут -> стоп, лесенка, трейлинг, временной стоп
87. ОТЧЕТ report.py в 21:30 -> что умерло, что заплатило, что вызывает вопросы

открытый mint authority — это не вопрос оценки. это факт, а факты бесплатны. Grok видит только те токены, которые уже прошли все проверки, доступные скрипту.

boan - inline image

05. помести все числа в один файл

сохрани как config.py. каждое число на столе живет здесь, поэтому при перенастройке ты редактируешь один файл и больше ничего. это мои настройки, заточенные под тикет в $25. они не рекомендация, а стартовая точка, которую ты будешь двигать.

python
1# config.py
2# каждое число на столе живет здесь. при перенастройке ты редактируешь только этот файл.
3
4MODEL = "grok-4.7" # проверь console.x.ai -> Models, если API его отклонит
5PAPER = True # первая неделя: фейковые исполнения по реальным ценам. переключай только после прочтения лога
6
7TICKET_USD = 25 # фиксированный. размер никогда не берется от прошлой победы
8MAX_OPEN = 4 # 4 x $25 = максимум $100 в рынке
9MAX_ENTRIES_PER_DAY = 6
10DAILY_LOSS_HALT_USD = 50 # реализованный убыток за сегодня достиг этого -> никаких новых входов до завтра
11COOLDOWN_HOURS = 24 # запрет на повторный вход в токен, из которого ты только что вышел
12
13FACTS = { # фильтр рагпулов. только код, без модели
14 "max_risk_score": 40, # score_normalised из rugcheck, 0-100, выше = рискованнее
15 "min_lp_locked_pct": 90, # крупнейший пул: LP заблокирован или сожжен
16 "max_top10_pct": 30, # топ-10 холдеров, пулы и блокировщики исключены
17 "max_dev_pct": 5, # объем предложения, всё ещё лежащий на кошельке создателя
18 "max_insiders": 0, # холдеры с флагом инсайдера + совпадения в графе инсайдеров
19 "min_liquidity_usd": 30000,
20 "max_ticket_share": 0.01, # твой тикет никогда не превышает 1% пула
21 "min_age_min": 30, # моложе этого — любой отчет всё ещё гадание
22 "max_age_hours": 72,
23}
24
25MIN_CONFIDENCE = 0.7 # если Grok говорит BUY ниже этого -> считается как SKIP
26
27EXIT = {
28 "stop_pct": -35, # жесткий стоп от точки входа
29 "ladder": [(100, 0.50), (200, 0.25)], # +100% продает половину, +200% продает четверть
30 "trail_pct": 30, # остаток: выход, когда цена падает на 30% от пика
31 "time_stop_hours": 6, # нет +20% через 6 часов -> выход, мертвые деньги
32 "time_stop_min_pct": 20,
33 "liq_drop_pct": 40, # ликвидность пула упала на 40% от входа -> немедленный выход
34}
35
36LOG = "checks.csv"
37POSITIONS = "positions.json"
38TRADES = "trades.csv"
text
1ФИКСИРОВАННЫЙ ТИКЕТ. размер никогда не растет из-за того, что последние три сделки были плюсовыми.
2БОТ ЧИТАЕТ config.py, ОН НИКОГДА ЕГО НЕ ПИШЕТ. число меняется только тогда, когда ты его меняешь.
3ФИЛЬТР ОСЛАБЛЯЕТСЯ ПИСЬМЕННО. ты меняешь число — ты в тот же день объясняешь почему в чате.

06. запускай лимиты раньше всего остального

сохрани как book.py. самая дешевая проверка на столе — та, которая вообще не дергает API. если сегодня уже потеряно $50, стол даже не посмотрит на токен. если открыто четыре позиции — то же самое. этот файл также является памятью стола: два файла, которые ты можешь открыть сам, positions.json и trades.csv.

python
1# book.py
2# позиции, сделки, лимиты. память стола живет в двух файлах, которые ты можешь открыть сам.
3import csv, json, os, sys, time
4from config import (POSITIONS, TRADES, TICKET_USD, MAX_OPEN, MAX_ENTRIES_PER_DAY,
5 DAILY_LOSS_HALT_USD, COOLDOWN_HOURS)
6
7def load() -> dict:
8 return json.load(open(POSITIONS)) if os.path.exists(POSITIONS) else {}
9
10def save(book: dict):
11 json.dump(book, open(POSITIONS, "w"), indent=2)
12
13def trades() -> list[dict]:
14 return list(csv.DictReader(open(TRADES))) if os.path.exists(TRADES) else []
15
16def record(mint, symbol, action, usd, pnl, reason):
17 new = not os.path.exists(TRADES)
18 with open(TRADES, "a", newline="") as f:
19 w = csv.DictWriter(f, fieldnames=["time", "mint", "symbol", "action", "usd", "pnl", "reason"])
20 if new:
21 w.writeheader()
22 w.writerow({"time": time.strftime("%Y-%m-%d %H:%M"), "mint": mint, "symbol": symbol,
23 "action": action, "usd": round(usd, 2), "pnl": round(pnl, 2), "reason": reason})
24
25def today_pnl() -> float:
26 day = time.strftime("%Y-%m-%d")
27 return sum(float(t["pnl"]) for t in trades() if t["time"].startswith(day))
28
29def guard(mint: str) -> str | None:
30 """Лимиты проверяются до любых сетевых вызовов. Заблокированный вход ничего не стоит."""
31 day = time.strftime("%Y-%m-%d")
32 book = load()
33 if today_pnl() <= -DAILY_LOSS_HALT_USD: return "halted_daily_loss"
34 if mint in book: return "already_open"
35 if len(book) >= MAX_OPEN: return "max_open"
36 opens = [t for t in trades() if t["action"] == "open" and t["time"].startswith(day)]
37 if len(opens) >= MAX_ENTRIES_PER_DAY: return "max_entries_today"
38 cutoff = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time() - COOLDOWN_HOURS * 3600))
39 if any(t["mint"] == mint and t["action"] == "close" and t["time"] >= cutoff for t in trades()):
40 return "cooldown"
41 return None
42
43def open_position(mint, symbol, price, liq_usd, usd=TICKET_USD):
44 book = load()
45 book[mint] = {"symbol": symbol, "entry": price, "qty0": usd / price, "qty": usd / price,
46 "peak": price, "liq0": liq_usd, "opened": time.time(), "steps": 0}
47 save(book)
48 record(mint, symbol, "open", usd, 0, "entry")
49
50def sell(mint, frac_of_original, price, reason) -> float:
51 """Продает долю от ИСХОДНОГО размера (1.0 = всё, что осталось). Возвращает реализованный pnl."""
52 book = load()
53 p = book[mint]
54 q = min(p["qty"], p["qty0"] * frac_of_original)
55 pnl = q * (price - p["entry"])
56 p["qty"] -= q
57 action = "close" if p["qty"] <= p["qty0"] * 1e-6 else "partial"
58 record(mint, p["symbol"], action, q * price, pnl, reason)
59 if action == "close":
60 del book[mint]
61 save(book)
62 return pnl
63
64if __name__ == "__main__":
65 # лайв-режим: после покупки на своем кошельке -> python book.py add <mint> <usd> <price> <liq_usd>
66 # после ручной продажи -> python book.py close <mint> <price>
67 cmd = sys.argv[1]
68 if cmd == "add":
69 mint, usd, price, liq = sys.argv[2], float(sys.argv[3]), float(sys.argv[4]), float(sys.argv[5])
70 open_position(mint, mint[:6], price, liq, usd)
71 elif cmd == "close":
72 print(round(sell(sys.argv[2], 1.0, float(sys.argv[3]), "manual"), 2))

07. пропиши выход до входа

большинство решает, когда продавать, глядя на зеленую свечу. это худший момент для любых решений. на этом столе каждый выход существует до покупки токена, а бот просто проверяет его каждые 10 минут:

  • ликвидность просела на 40% от входа: выход, полностью, без вопросов
  • минус 35%: выход
  • плюс 100%: половина уходит, остальное — деньги рынка
  • плюс 200%: уходит еще четверть
  • после первого тейка остаток выходит, когда цена падает на 30% от пика
  • шесть часов без +20%: выход, слот стоит дороже надежды

сохрани как watch.py:

python
1# watch.py
2# каждая открытая позиция, каждые 10 минут. ничего не печатает, если ничего не изменилось.
3import time
4from config import EXIT, PAPER
5from market import pool
6import book
7
8def watch() -> list[str]:
9 events = []
10 for mint, p in list(book.load().items()):
11 try:
12 m = pool(mint)
13 except Exception as e:
14 events.append(f"{p['symbol']}: прайс-фид упал ({e}), держим, попробуем снова")
15 continue
16 if not m or m["price"] <= 0:
17 events.append(f"{p['symbol']}: пул исчез. считаем рагпулом, продавай что можешь")
18 book.sell(mint, 1.0, 0.0, "pool_gone")
19 continue
20
21 price = m["price"]
22 b = book.load(); s = b[mint]
23 s["peak"] = max(s["peak"], price); book.save(b)
24 pct = (price / s["entry"] - 1) * 100
25 hours = (time.time() - s["opened"]) / 3600
26
27 def out(frac, why):
28 pnl = book.sell(mint, frac, price, why)
29 verb = "продано" if PAPER else "ПРОДАВАЙ СЕЙЧАС в своем кошельке"
30 size = "остаток" if frac >= 1 else f"{int(frac * 100)}%"
31 events.append(f"{s['symbol']}: {verb} {size} на {pct:+.0f}% ({why}), pnl ${pnl:+.2f}")
32
33 if m["liq_usd"] < s["liq0"] * (1 - EXIT["liq_drop_pct"] / 100):
34 out(1.0, "liquidity_pulled"); continue
35 if pct <= EXIT["stop_pct"]:
36 out(1.0, "stop"); continue
37 ladder = EXIT["ladder"]
38 if s["steps"] < len(ladder) and pct >= ladder[s["steps"]][0]:
39 out(ladder[s["steps"]][1], f"take_profit_{ladder[s['steps']][0]}")
40 b = book.load()
41 if mint in b:
42 b[mint]["steps"] += 1; book.save(b)
43 continue
44 if s["steps"] > 0 and price <= s["peak"] * (1 - EXIT["trail_pct"] / 100):
45 out(1.0, "trailing_stop"); continue
46 if hours >= EXIT["time_stop_hours"] and pct < EXIT["time_stop_min_pct"]:
47 out(1.0, "time_stop")
48 return events
49
50if __name__ == "__main__":
51 for e in watch():
52 print(e)
text
1ЛИКВИДНОСТЬ ПЕРВАЯ. вытащенный пул бьет любое другое правило, даже если позиция в плюсе.
2ТРЕЙЛИНГ ВКЛЮЧАЕТСЯ ПОСЛЕ ПЕРВОГО ТЕЙКА. до этого -35% — единственный пол.
3МЕРТВЫЕ ДЕНЬГИ — ЭТО ТОЖЕ УБЫТОК. шесть пустых часов освобождают слот для следующего токена.
4ТИШИНА — ЭТО СТАТУС. watch.py ничего не печатает, если ничего не изменилось, так что тихий чат значит, что смотреть туда не нужно.
boan - inline image

08. изучи 14 способов смерти токена

если бы мне пришлось выбросить всё вышеперечисленное и оставить одну вещь, это была бы она. она работает и без всяких ботов: пройдись вручную по тем же 14 проверкам на rugcheck.xyz и dexscreener перед следующей покупкой, и ты пропустишь большинство токенов, о которых собирался пожалеть.

13 проверок — это код. сравнения, без модели, без мнений. 14-я — единственная, которой нужен Grok.

#

проверка

убивает, когда

почему

1

уже рагнули

Rugcheck помечает его как rugged

кто-то уже сделал это

2

mint authority

всё ещё открыт

дев может напечатать новую эмиссию прямо в твой бэг

3

freeze authority

всё ещё открыт

дев может заморозить твои токены, ты не сможешь продать

4

флаги опасности

любой риск уровня danger

Rugcheck уже увидел то, что тебе пришлось бы опровергать

5

risk score

выше 40/100

мелкие предупреждения складываются

6

блокировка LP

крупнейший пул заблокирован или сожжен менее чем на 90%

разблокированная ликвидность — это кнопка для рагпула

7

топ-10 холдеров

больше 30%, пулы и блокировщики исключены

десять кошельков могут вместе закрыть твою сделку

8

кошелек дева

создатель всё ещё держит больше 5%

дев — первый продавец

9

инсайдеры / бандлы

любой холдер-инсайдер или совпадение в графе инсайдеров

кошельки, профинансированные вместе, продают вместе

10

глубина пула

ликвидность меньше $30k

ты станешь чьим-то экзитом

11

доля тикета

твои $25 — это больше 1% пула

твоя собственная покупка сдвигает цену

12

возраст

меньше 30 мин или больше 72ч

слишком свежий для любого отчета, либо движение уже прошло

13

есть ли продажи

20+ покупок за последний час, ноль продаж

это форма ханипота

14

чтение X (Grok)

нет постов, скопированный CA, купленный хайп, история рагпулов

та часть, которую не вернет ни один API

boan - inline image

09. позволь коду убить очевидных

проверки с 1 по 9. он тянет один отчет и оставляет только те поля, которые читает стол. Grok никогда не видит сырой отчет: тяжелый пейлоад жрет токены и снижает точность.

одна деталь, которую люди упускают: собственный сейв пула и блокировщики сидят в списке топ-холдеров. посчитай их — и любой токен покажется китовым. код выкидывает их до того, как суммировать топ-10.

python
1# rugcheck.py
2# один отчет на токен, обрезанный до полей, которые читает стол. Grok никогда не видит сырой отчет.
3import requests
4from config import FACTS
5
6RC = "https://api.rugcheck.xyz/v1/tokens"
7
8def report(mint: str) -> dict:
9 r = requests.get(f"{RC}/{mint}/report", timeout=20)
10 r.raise_for_status()
11 d = r.json()
12 token = d.get("token") or {}
13 known = d.get("knownAccounts") or {}
14
15 def is_pool(h): # AMM-сейвы и блокировщики сидят в топ-холдерах, они не киты
16 tag = known.get(h.get("owner")) or known.get(h.get("address")) or {}
17 return str(tag.get("type", "")).upper() in ("AMM", "LOCKER")
18
19 holders = [h for h in (d.get("topHolders") or []) if not is_pool(h)]
20 markets = sorted(d.get("markets") or [],
21 key=lambda m: ((m.get("lp") or {}).get("baseUSD") or 0)
22 + ((m.get("lp") or {}).get("quoteUSD") or 0),
23 reverse=True)
24 lp = (markets[0].get("lp") or {}) if markets else {}
25 supply = token.get("supply") or 0
26 risks = d.get("risks") or []
27
28 return {
29 "mint": mint,
30 "symbol": (d.get("tokenMeta") or {}).get("symbol"),
31 "rugged": bool(d.get("rugged")),
32 "risk_score": d.get("score_normalised"),
33 "danger": [x.get("name") for x in risks if x.get("level") == "danger"],
34 "warn": [x.get("name") for x in risks if x.get("level") == "warn"],
35 "mint_authority": token.get("mintAuthority", d.get("mintAuthority")),
36 "freeze_authority": token.get("freezeAuthority", d.get("freezeAuthority")),
37 "lp_locked_pct": lp.get("lpLockedPct", d.get("lpLockedPct")),
38 "top10_pct": round(sum(h.get("pct") or 0 for h in holders[:10]), 2) if holders else None,
39 "dev_pct": round((d.get("creatorBalance") or 0) / supply * 100, 2) if supply else None,
40 "insiders": sum(1 for h in holders if h.get("insider")) + (d.get("graphInsidersDetected") or 0),
41 "holders": d.get("totalHolders"),
42 }
43
44def fact_kill(t: dict) -> str | None:
45 """Простые сравнения. Первый провал побеждает, причина логируется."""
46 if t["risk_score"] is None: return "no_report"
47 if t["rugged"]: return "already_rugged"
48 if t["mint_authority"]: return "mint_open"
49 if t["freeze_authority"]: return "freeze_open"
50 if t["danger"]: return "danger:" + t["danger"][0]
51 if t["risk_score"] > FACTS["max_risk_score"]: return "risk_score"
52 if t["lp_locked_pct"] is None or t["lp_locked_pct"] < FACTS["min_lp_locked_pct"]:
53 return "lp_unlocked"
54 if t["top10_pct"] is None or t["top10_pct"] > FACTS["max_top10_pct"]:
55 return "top10_heavy"
56 if t["dev_pct"] is None or t["dev_pct"] > FACTS["max_dev_pct"]:
57 return "dev_holds"
58 if t["insiders"] > FACTS["max_insiders"]: return "insiders"
59 return None
boan - inline image

10. проверяй пул, а не только контракт

проверки с 10 по 13. контракт может быть идеальным, но пул всё равно не выпустит тебя наружу. этот скрипт читает самый глубокий пул для токена и задает четыре скучных вопроса: достаточно ли в нем денег, насколько велик мой тикет рядом с ним, сколько ему лет и продает ли кто-нибудь вообще.

python
1# market.py
2# сам пул: глубина, возраст, цена и может ли кто-то вообще продать.
3import time
4import requests
5from config import FACTS, TICKET_USD
6
7DS = "https://api.dexscreener.com/tokens/v1/solana"
8
9def pool(mint: str) -> dict | None:
10 r = requests.get(f"{DS}/{mint}", timeout=15)
11 r.raise_for_status()
12 data = r.json()
13 pairs = data if isinstance(data, list) else (data.get("pairs") or [])
14 pairs = [p for p in pairs if (p.get("baseToken") or {}).get("address") == mint]
15 if not pairs:
16 return None
17 p = max(pairs, key=lambda x: (x.get("liquidity") or {}).get("usd") or 0)
18 h1 = (p.get("txns") or {}).get("h1") or {}
19 born = p.get("pairCreatedAt")
20 return {
21 "symbol": (p.get("baseToken") or {}).get("symbol"),
22 "price": float(p.get("priceUsd") or 0),
23 "liq_usd": (p.get("liquidity") or {}).get("usd") or 0,
24 "age_min": round((time.time() * 1000 - born) / 60000) if born else None,
25 "buys_1h": h1.get("buys", 0),
26 "sells_1h": h1.get("sells", 0),
27 "vol_1h": (p.get("volume") or {}).get("h1"),
28 "url": p.get("url"),
29 }
30
31def market_kill(m: dict | None) -> str | None:
32 if not m: return "no_pool"
33 if m["price"] <= 0: return "no_price"
34 if m["liq_usd"] < FACTS["min_liquidity_usd"]: return "thin_pool"
35 if TICKET_USD / m["liq_usd"] > FACTS["max_ticket_share"]: return "ticket_too_big"
36 if m["age_min"] is None or m["age_min"] < FACTS["min_age_min"]:
37 return "too_fresh"
38 if m["age_min"] > FACTS["max_age_hours"] * 60: return "too_old"
39 if m["buys_1h"] >= 20 and m["sells_1h"] == 0: return "nobody_can_sell"
40 return None

11. позволь Grok читать то, что не может код

проверка 14. вот почему стол работает на Grok, а не на любой другой модели: он может искать по X, пока думает. токен может пройти все 13 проверок и всё равно оказаться копипастой с другим адресом контракта, или запуском, где сорок аккаунтов, созданных на прошлой неделе, запостили одно и то же предложение в одну и ту же минуту. ни один API этого не вернет. X — вернет.

сохрани как grok.py. это единственный файл, который читает ключ, и единственное место, где стол общается с xAI:

python
1# grok.py
2# единственный файл, в котором хранится ключ, и единственное место, где деск общается с xAI.
3import os, json, datetime, requests
4from config import MODEL
5
6URL = "https://api.x.ai/v1/responses"
7
8def _key() -> str:
9 k = os.environ.get("XAI_API_KEY")
10 if not k and os.path.exists(".env"):
11 for line in open(".env"):
12 if line.startswith("XAI_API_KEY="):
13 k = line.split("=", 1)[1].strip().strip('"')
14 if not k:
15 raise RuntimeError("no XAI_API_KEY in the environment or in .env")
16 return k
17
18def _text(resp: dict) -> str:
19 if isinstance(resp.get("output_text"), str):
20 return resp["output_text"]
21 parts = []
22 for item in resp.get("output") or []:
23 if item.get("type") == "message":
24 for c in item.get("content") or []:
25 if c.get("type") in ("output_text", "text"):
26 parts.append(c.get("text") or "")
27 return "\n".join(parts)
28
29def ask(system: str, payload: dict, read_x: bool = False) -> dict:
30 """Один вызов: JSON на вход, JSON на выход. Всё, что не JSON, вызывает исключение, а исключение означает SKIP (пропуск) на верхнем уровне."""
31 body = {"model": MODEL,
32 "input": [{"role": "system", "content": system},
33 {"role": "user", "content": json.dumps(payload)}]}
34 if read_x:
35 since = (datetime.date.today() - datetime.timedelta(days=3)).isoformat()
36 body["tools"] = [{"type": "x_search", "from_date": since}]
37 body["max_turns"] = 2 # два раунда поиска, затем модель обязана ответить
38 r = requests.post(URL, timeout=180, json=body,
39 headers={"Authorization": f"Bearer {_key()}"})
40 r.raise_for_status()
41 text = _text(r.json())
42 start, end = text.find("{"), text.rfind("}")
43 if start == -1:
44 raise ValueError(f"no json in answer: {text[:200]}")
45 return json.loads(text[start:end + 1])

сохрани как prompts.py. это тот файл, который ты будешь перечитывать:

python
1# prompts.py
2# единственный промпт для Grok на деске. именно этот файл ты будешь перечитывать.
3
4JUDGE_PROMPT = """
5Ты — RUG DESK. Solana-мемкоин только что прошёл все жёсткие проверки в коде:
6полномочия (authorities), LP, холдеров, кошелёк дева, инсайдеров, глубину пула, возраст.
7Не перепроверяй эти цифры. Ты решаешь, зайдёт ли один плоский тикет.
8Ты никогда не определяешь размер позиции и никогда не выбираешь точки выхода.
9
10ВХОДНЫЕ ДАННЫЕ: {"token": {...факты из rugcheck...}, "pool": {...факты из dexscreener...}}
11
12ШАГ 1. Найди в X тикер и адрес контракта за последние 72 часа.
13ШАГ 2. Оценивай только то, чего код не видит:
14 - складываются ли риски уровня warn во что-то более серьёзное вместе
15 - кто запостил первым: дев, реальный аккаунт с историей или волна свежих аккаунтов
16 - органика или покупка: одинаковые формулировки, одна и та же минута, аккаунты без прошлого
17 - совпадает ли адрес контракта в этих постах с тем, что в ВХОДНЫХ ДАННЫХ
18 - был ли этот тикер или этот дев замешан в раге раньше
19
20ВОЗВРАЩАЙ ТОЛЬКО JSON:
21{"verdict": "BUY" | "SKIP", "confidence": 0.0-1.0,
22 "why": "максимум две строки", "x_read": "одна строка о том, как выглядит X",
23 "main_risk": "одна строка"}
24
25Ноль постов в X — это тоже ответ: никто не знает, что он существует. SKIP.
26Другой адрес контракта под тем же тикером в X: риск копии. SKIP.
27НИКОГДА не отвечай BUY, если нужное тебе поле равно null.
28НИКОГДА не упоминай ценовые цели. Ты их не знаешь.
29"""

12. собираем всё в одну команду

один адрес контракта на входе, один вердикт на выходе. лимиты, факты, пул, Grok — именно в таком порядке, и первый отказ всё останавливает:

python
1# check.py
2# один адрес контракта на входе, один вердикт на выходе. запускается каждый раз, когда токен попадает на твой деск.
3import csv, json, os, sys, time
4from config import LOG, MIN_CONFIDENCE, PAPER, TICKET_USD
5from rugcheck import report, fact_kill
6from market import pool, market_kill
7from grok import ask
8from prompts import JUDGE_PROMPT
9import book
10
11def log(row: dict):
12 new = not os.path.exists(LOG)
13 with open(LOG, "a", newline="") as f:
14 w = csv.DictWriter(f, fieldnames=["time", "mint", "symbol", "stage", "verdict",
15 "confidence", "reason"])
16 if new:
17 w.writeheader()
18 w.writerow({k: row.get(k) for k in w.fieldnames})
19
20def check(mint: str) -> dict:
21 if (g := book.guard(mint)): # лимиты, бесплатно
22 return {"stage": "limits", "verdict": "SKIP", "reason": g}
23
24 try:
25 token = report(mint) # фильтр рагов, бесплатно
26 except Exception as e:
27 return {"stage": "facts", "verdict": "SKIP", "reason": f"rugcheck failed: {e}"}
28 if (k := fact_kill(token)):
29 return {"stage": "facts", "verdict": "SKIP", "reason": k, "symbol": token["symbol"]}
30
31 try:
32 m = pool(mint) # пул, бесплатно
33 except Exception as e:
34 return {"stage": "pool", "verdict": "SKIP", "reason": f"dexscreener failed: {e}"}
35 if (k := market_kill(m)):
36 return {"stage": "pool", "verdict": "SKIP", "reason": k, "symbol": token["symbol"]}
37
38 try:
39 ans = ask(JUDGE_PROMPT, {"token": token, "pool": m}, read_x=True) # единственный платный шаг
40 except Exception as e:
41 return {"stage": "grok", "verdict": "SKIP", "reason": f"grok failed: {e}"}
42
43 verdict, conf = ans.get("verdict"), ans.get("confidence") or 0
44 if verdict == "BUY" and conf < MIN_CONFIDENCE:
45 verdict = "SKIP"
46 ans["why"] = f"low confidence {conf}"
47 return {**ans, "stage": "grok", "verdict": verdict, "symbol": m["symbol"] or token["symbol"],
48 "reason": ans.get("why"), "price": m["price"], "liq_usd": m["liq_usd"], "url": m["url"]}
49
50if __name__ == "__main__":
51 mint = sys.argv[1].strip()
52 v = check(mint)
53 log({"time": time.strftime("%Y-%m-%d %H:%M"), "mint": mint, **v})
54 if v["verdict"] == "BUY":
55 if PAPER:
56 book.open_position(mint, v["symbol"], v["price"], v["liq_usd"])
57 v["action"] = f"PAPER BUY ${TICKET_USD} at {v['price']}"
58 else:
59 v["action"] = (f"APPROVAL NEEDED: buy ${TICKET_USD} of {v['symbol']} in your own wallet, "
60 f"then run: python book.py add {mint} {TICKET_USD} <fill price> {v['liq_usd']}")
61 print(json.dumps(v, indent=2))

чтобы этим пользоваться, сканер не нужен. CA из колл-канала, поста или сообщения друга: скажи боту «check <CA>», и он выполнит одну строку. Ответ будет выглядеть примерно так (пример структуры, не реальный токен):

json
1{
2 "verdict": "SKIP",
3 "confidence": 0.78,
4 "why": "проходит все жёсткие проверки, но первые 30 постов сделаны аккаунтами, созданными на этой неделе, с одинаковыми формулировками.",
5 "x_read": "один реальный аккаунт, волна свежих, расхождений по CA нет",
6 "main_risk": "купленный хайп, покупатели уйдут, как только закончатся посты",
7 "stage": "grok",
8 "symbol": "EXAMPLE",
9 "reason": "проходит все жёсткие проверки, но первые 30 постов сделаны аккаунтами, созданными на этой неделе, с одинаковыми формулировками."
10}
boan - inline image
text
1СНАЧАЛА ФАКТЫ, ПОТОМ МНЕНИЯ. Grok никогда не решает, открыт ли минт.
2НЕУДАЧНЫЙ ВЫЗОВ — ЭТО SKIP. Rugcheck упал, DexScreener упал, Grok упал, кривой JSON: SKIP.
3NULL — ЭТО НЕ ЧИСТОТА. Если поле не вернулось, оно убивает токен, а не пропускает его.
4ОДИН ВЕРДИКТ НА ТОКЕН. Никогда не перезапускай проверку, пока она не выдаст BUY. Если ты не согласен — ты не согласен с config.py.
5ЧИТАЙ ОТКАЗЫ, А НЕ ПОКУПКИ. Покупки радуют. Причины отказов показывают, работает ли фильтр.

13. три рутины, каждая в одно предложение

никаких конструкторов воркфлоу. ты один раз объясняешь боту каждую рутину одним предложением, и он показывает тебе следующий запуск. вот мои, слово в слово:

text
1Каждые 10 минут в /workspace/desk запускай python watch.py.
2Если ничего не выводит — молчи. Если что-то выводит — напиши сюда слово в слово.
text
1Каждые 30 минут в /workspace/desk запускай python scan.py.
2Публикуй только вердикты BUY: символ, уверенность, x_read.
3Если Rugcheck или DexScreener упали, скажи какой именно один раз, а не при каждом запуске.
text
1Каждый день в 21:30 в /workspace/desk запускай python report.py и публикуй результат здесь.
2Добавь одну вещь, которая сегодня сработала, и одну цифру в config.py, которую ты бы поставил под сомнение, с объяснением почему.
3Никогда не меняй эту цифру сам.

два файла, которые запускают эти рутины. сохрани как report.py:

python
1# report.py
2# вечерний отчёт. всё в нём берётся из checks.csv и trades.csv, ничего из памяти.
3import csv, os, time
4from collections import Counter
5from config import LOG, PAPER
6import book
7
8day = time.strftime("%Y-%m-%d")
9checks = [r for r in csv.DictReader(open(LOG))] if os.path.exists(LOG) else []
10checks = [r for r in checks if r["time"].startswith(day)]
11done = [t for t in book.trades() if t["time"].startswith(day) and t["action"] != "open"]
12
13by_stage = Counter(r["stage"] for r in checks if r["verdict"] == "SKIP")
14buys = [r for r in checks if r["verdict"] == "BUY"]
15wins = [t for t in done if float(t["pnl"]) > 0]
16reasons = Counter(r["reason"] for r in checks if r["stage"] in ("facts", "pool"))
17
18print(f"EVENING REPORT {day} {'(PAPER)' if PAPER else '(LIVE)'}")
19print(f"checked: {len(checks)}")
20print(f"killed by rug filter: {by_stage['facts']} | by pool: {by_stage['pool']} | "
21 f"by Grok: {by_stage['grok']} | by limits: {by_stage['limits']}")
22print(f"bought: {len(buys)} | open now: {len(book.load())}")
23print(f"realized pnl today: ${book.today_pnl():+.2f}")
24if done:
25 print(f"green exits: {len(wins)}/{len(done)}")
26 best = max(done, key=lambda t: float(t["pnl"]))
27 worst = min(done, key=lambda t: float(t["pnl"]))
28 print(f"best: {best['symbol']} ${float(best['pnl']):+.2f} | worst: {worst['symbol']} ${float(worst['pnl']):+.2f}")
29if reasons:
30 top, n = reasons.most_common(1)[0]
31 print(f"most common kill: {top} ({n}x)")

и scan.py — необязательный источник лидов. он тянет свежие токены Solana, которые только что оплатили профиль на DexScreener. оплаченный профиль — не показатель качества, он лишь значит, что дев потратил деньги. остальное решит фильтр:

python
1# scan.py
2# необязательный источник лидов: свежие токены Solana, только что оплатившие профиль на DexScreener.
3# оплаченный профиль — не сигнал качества, он лишь значит, что дев потратил деньги. решает фильтр.
4import csv, os, subprocess, sys
5import requests
6from config import LOG
7
8seen = {r["mint"] for r in csv.DictReader(open(LOG))} if os.path.exists(LOG) else set()
9r = requests.get("https://api.dexscreener.com/token-profiles/latest/v1", timeout=15)
10r.raise_for_status()
11fresh = [t["tokenAddress"] for t in r.json()
12 if t.get("chainId") == "solana" and t.get("tokenAddress") not in seen]
13
14for mint in fresh[:5]: # по пять за запуск, чтобы один активный час не съел весь бюджет API
15 subprocess.run([sys.executable, "check.py", mint])

последнее на сегодня: Settings, General, Auto-review. добавь два правила Ask first (спрашивать сначала) — они остановят действие и будут ждать тебя независимо от того, что думает любая рутина:

text
1Спрашивай перед любым подключением кошелька, подписью, свопом или переводом.
2Спрашивай перед редактированием любого файла с именем config.py.
boan - inline image
boan - inline image

14. неделя на бумаге до первого доллара

PAPER = True означает, что деск делает всё по-настоящему, кроме денег. реальные токены, реальные цены, реальные выходы, фейковые исполнения. через семь дней открой checks.csv и прочитай его так, будто его писал незнакомец.

что искать: какая проверка убивает чаще всего, купил бы ты сам те токены, где вышел BUY, и не выглядят ли ошибочными причины SKIP. бумажное исполнение происходит по цене на экране, реальное — никогда, поэтому считай бумажный результат потолком, а не прогнозом.

когда перейдёшь в лайв, переключи PAPER на False, и ничего не изменится, кроме последнего шага. check.py перестаёт покупать и вместо этого выдаёт строку подтверждения: купи $25 сам в своём кошельке, а затем одной командой занеси это в книгу, чтобы watch.py начал его охранять.

когда всё ломается

здесь дело касается денег, поэтому для каждого сбоя ответ должен быть записан до того, как он случится.

text
1401 от xAI -> плохой ключ. Перехвати управление, перепиши .env, снова запусти curl из шага 03.
2400 / 404 от xAI -> изменилось имя модели. поправь MODEL в config.py, больше ничего.
3429 от xAI -> rate limit. этот токен — SKIP, следующий запуск идёт дальше. никогда не зацикливай.
4ошибка про x_search -> твой MODEL не умеет искать в X. выбери тот, что умеет, в console.x.ai -> Models.
5Grok отвечает текстом -> ValueError, логируется, SKIP. никогда не превращай абзац в сделку.
6rugcheck 404 или пусто -> слишком свежий для индекса. SKIP. свежее не значит чистое.
7lp_unlocked на всём -> у некоторых типов пулов вообще нет LP-токена. открой такой на rugcheck сам,
8 прежде чем трогать эту цифру, и меняй её осознанно.
9no_pool -> ещё не торгуется на DEX или не Solana. SKIP.
10рутины замолчали -> Grok Bot ставит рутины на паузу, если тебя долго не было.
11 открой Routines и включи их обратно.

счёт

всё до судьи бесплатно: лимиты, Rugcheck, DexScreener. единственный платный шаг — один вызов Grok на токен, прошедший все 13 проверок, с включённым поиском по X.

text
1cost_per_token = input_tokens / 1_000_000 * price_per_M_input
2 + output_tokens / 1_000_000 * price_per_M_output
3 + posts_fetched / 1_000 * 5 # поиск в X: $5 за 1000 найденных постов
4
5max_turns = 2 ограничивает поиск двумя раундами, поэтому posts_fetched остаётся небольшим.
6каждый ответ сообщает свой x_posts_fetched, так что уже в первый день ты увидишь реальную цифру.
7
8цена: [цена из console.x.ai]

в чём люди ошибаются: счёт растёт от выживших, а не от сканера. scan.py может подавать на деск 240 токенов в день, и большинство из них умрут бесплатно, прежде чем Grok вообще о них узнает.

boan - inline image

важная часть

это мой сетап, а не твоя стратегия.

каждая цифра в config.py — моя, подобранная под тикет в $25 и мою личную готовность смотреть, как что-то уходит в ноль. большинство мемкоинов действительно уходят в ноль, и большинство тех, кто ими торгует, теряют деньги. фильтр не делает токен хорошим. он убирает очевидные способы потерять деньги и заставляет тебя читать, почему умер каждый токен.

погоняй неделю на бумаге. читай отказы. меняй цифры там, где не согласен, и делай это осознанно. копируй структуру, а не константы. не финансовая рекомендация.

код убивает, Grok читает X, подписываешь ты. скрипт никогда не принимает решений на своё усмотрение, Grok никогда не получает калькулятор, и никто, кроме тебя, не получает доступ к кошельку.

сохрани это перед следующей покупкой. подписывайся, если планируешь запустить то же самое, такого контента будет больше 🫶

мой tg - t.me/+8wAXS0nHWgA2MGEy

мой github - github.com/0xboan

торгуй здесь - fomo.family/r/0xboan

Сохранение в один клик

Используйте YouMind для глубокого чтения вирусных статей с помощью ИИ

Сохраняйте источники, задавайте точные вопросы, обобщайте аргументы и превращайте вирусные статьи в полезные заметки в одном рабочем пространстве ИИ.

Исследовать YouMind
Для авторов

Превратите ваш Markdown в аккуратную статью для 𝕏

Когда вы публикуете длинные тексты, изображения, таблицы и блоки кода, форматирование в 𝕏 становится мучением. YouMind превращает полный черновик в Markdown в чистую статью, готовую к публикации в 𝕏.

Попробовать Markdown для 𝕏

Другие паттерны для анализа

Недавние виральные статьи

Смотреть другие виральные статьи