більшість людей знайомляться з Grok Bot через чийсь скріншот PnL, відкривають його, наводять на графік і втрачають перші $50 на токені, який помер ще до того, як вони його купили. проблема була не в боті. йому просто ніхто не пояснив, як виглядає «мертвий».
ось цей сетап я б зібрав знову сьогодні ввечері, якби довелося починати спочатку. один бот, одна папка, десять маленьких файлів. він не полює на 100x. його головна робота — вбивати токени, а ті кілька, що виживають, все одно потребують, щоб Grok прочитав X, перш ніж хоча б долар кудись рушить.
кроки з 01 по 07 — це перший вечір: бот, ключ, ліміти, виходи. з 08 по 12 — фільтр рагпулів, 14 перевірок, кожна з яких прописана кодом. 13 і 14 переводять усе на автопілот, спершу лише на папері.
якщо ви читали мій пост про стіл із восьми агентів, то ось фундамент, на якому той стіл стоїть.
https://x.com/0xboan/status/2092226208234647626
як цим користуватися: відкрийте свій Grok Bot, вставте всю цю статтю і скажіть «збери цей стіл у /workspace/desk, паперовий режим, питай мене, перш ніж щось торкнеться гаманця». він сам напише кожен файл на своєму комп'ютері.
головне правило, якого треба триматися: код вбиває, 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 читає контракт: повноваження на емісію (mint authority), LP, холдерів, інсайдерів, гаманець розробника. DexScreener читає пул: глибину, вік, покупки проти продажів.
що робити. нічого. ніякої реєстрації, ніяких ключів для читання.
навіщо. факти йдуть перед думками. відкрите право на емісію — це не питання оцінки, це факт, а факти вбивають першими.
4. одноразовий гаманець (burner wallet), але не сьогодні
що це. свіжий Solana-гаманець, на якому ніколи нічого не лежало.
що робити. поки нічого. перший тиждень працюємо на папері.
навіщо. стіл ніколи не зберігає ключ. коли ви перейдете в лайв, він скаже вам, що купувати, а ви підпишете транзакцію самі.
02. найміть одного бота, а не вісьмох
мій стіл зараз тримає вісім ботів. так було не з самого початку, і у вас теж не має бути. вісім ботів у перший день — це вісім речей, які треба дебажити одночасно. один бот з одним завданням покаже вам, що знадобиться решті сімом пізніше.
оберіть Create your own і дайте йому це, слово в слово:
1Ім'я: RUG DESK2Робота: Стіл для Solana-мемкоїнів, спершу на папері3Опис: Збери та запусти стіл у /workspace/desk зі статті, яку я вставлю.4Кожен токен проходить через check.py, без винятків, без скорочень.5Ти ніколи не купуєш, не продаєш, не підписуєш і не переміщуєш кошти. Ти ніколи не редагуєш config.py, якщо я не попрошу6в цьому чаті. Ти ніколи не занижуєш параметри фільтра, щоб пропустити токен.7Повідомляй про кожне «вбивство» з причиною, а не зі своєю думкою про токен.8Якщо джерело впало, скажи яке саме і пропусти. Ніколи не вгадуй відсутню цифру.
останні два рядки важливіші за перші п'ять. бот, який вгадує відсутню цифру, рано чи пізно вгадає ту, що коштуватиме вам грошей.

03. тримайте ключ подалі від чату
усе, що ви пишете боту, потрапляє в лог. тому ключ іде у файл, набраний вами, на комп'ютері бота.
відкрийте комп'ютер бота, натисніть Take over, відкрийте термінал і запустіть це. команда запитає ключ, не виводячи його на екран, тому він ніколи не з'явиться в історії:
1mkdir -p /workspace/desk && cd /workspace/desk2read -rs -p "xai key: " K && printf 'XAI_API_KEY=%s\n' "$K" > .env && unset K3chmod 600 .env4pip install requests
потім переконайтеся, що ключ працює, перш ніж робити щось інше. один виклик, щоб потім ніколи не плутати поганий ключ із поганим промптом:
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"}'56-> ... "type":"output_text","text":"OK" ...
натисніть I'm done і поверніть комп'ютер боту. відтепер він може керувати столом, і при цьому досі не бачить ключа в чаті.

04. побачте всю воронку, перш ніж будувати її
вісім проходів. безкоштовні йдуть першими. лише те, що виживе після них, коштує виклику Grok, і лише те, що Grok назве BUY, коштує грошей. цього тижня — навіть не це.
10. ЛІД CA звідусіль: з поради, поста, scan.py -> один mint21. ЛІМІТИ book.py: денний збиток, відкриті слоти, кулдаун -> безкоштовно, взагалі без мережі32. ФАКТИ rugcheck.py: 10 жорстких відсівів -> відкритий mint, розблокований LP, жирний топ-10 гинуть тут43. ПУЛ market.py: глибина, вік, продажі -> тонкі пули та ханіпоти гинуть тут54. СУДДЯ grok.py + пошук по X, один виклик -> BUY або SKIP, одна причина, один ризик65. ВХІД папір: book.py за живою ціною -> лайв: ви підписуєте самі76. НАГЛЯД watch.py кожні 10 хвилин -> стоп, драбинка, трейлінг, часовий стоп87. ЗВІТ report.py о 21:30 -> що загинуло, що заплатило, що варто поставити під сумнів
відкрите право на емісію — це не питання оцінки. це факт, а факти безкоштовні. Grok бачить лише ті токени, які вже пройшли всі перевірки, здатні виконати скрипти.

05. помістіть усі цифри в один файл
збережіть як config.py. кожна цифра на столі живе тут, тому коли ви переналаштовуєте, ви редагуєте один файл і більше нічого. це мої налаштування, заточені під тікет у $25. вони не є рекомендацією, це лише стартова точка, яку ви будете рухати.
1# config.py2# кожна цифра на столі живе тут. коли ви переналаштовуєте, ви редагуєте цей файл і більше нічого.34MODEL = "grok-4.7" # перевірте console.x.ai -> Models, якщо API його відхиляє5PAPER = True # перший тиждень: фейкові угоди за реальними цінами. перемикайте лише після прочитання логу67TICKET_USD = 25 # фіксовано. розмір ніколи не залежить від останнього виграшу8MAX_OPEN = 4 # 4 x $25 = максимум $100 у ринку9MAX_ENTRIES_PER_DAY = 610DAILY_LOSS_HALT_USD = 50 # реалізований збиток за день досяг цього -> нових входів немає до завтра11COOLDOWN_HOURS = 24 # без повторного входу в токен, який ви щойно залишили1213FACTS = { # фільтр рагпулів. тільки код, без моделі14 "max_risk_score": 40, # rugcheck score_normalised, 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}2425MIN_CONFIDENCE = 0.7 # якщо Grok каже BUY нижче цього -> вважається SKIP2627EXIT = {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}3536LOG = "checks.csv"37POSITIONS = "positions.json"38TRADES = "trades.csv"
1ФІКСОВАНИЙ ТІКЕТ. розмір ніколи не зростає через те, що останні три були прибутковими.2БОТ ЧИТАЄ config.py, АЛЕ НІКОЛИ ЙОГО НЕ ПИШЕ. цифра змінюється лише тоді, коли ви її змінюєте.3ПОСЛАБЛЕННЯ ФІЛЬТРА ФІКСУЄТЬСЯ ПИСЬМОВО. ви змінили цифру — поясніть чому в чаті того ж дня.
06. запускайте ліміти перш за все
збережіть як book.py. найдешевша перевірка на столі — та, яка взагалі не звертається до API. якщо сьогодні вже втрачено $50, стіл навіть не дивиться на токен. якщо відкрито чотири позиції — те саме. цей файл також є пам'яттю столу: два файли, які ви можете відкрити самі, positions.json і trades.csv.
1# book.py2# позиції, угоди, ліміти. пам'ять столу живе у двох файлах, які ви можете відкрити самі.3import csv, json, os, sys, time4from config import (POSITIONS, TRADES, TICKET_USD, MAX_OPEN, MAX_ENTRIES_PER_DAY,5 DAILY_LOSS_HALT_USD, COOLDOWN_HOURS)67def load() -> dict:8 return json.load(open(POSITIONS)) if os.path.exists(POSITIONS) else {}910def save(book: dict):11 json.dump(book, open(POSITIONS, "w"), indent=2)1213def trades() -> list[dict]:14 return list(csv.DictReader(open(TRADES))) if os.path.exists(TRADES) else []1516def 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})2425def 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))2829def 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 None4243def 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")4950def 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"] -= q57 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 pnl6364if __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:
1# watch.py2# кожна відкрита позиція, кожні 10 хвилин. нічого не друкує, якщо нічого не змінилося.3import time4from config import EXIT, PAPER5from market import pool6import book78def 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 continue16 if not m or m["price"] <= 0:17 events.append(f"{p['symbol']}: пул зник. вважати рагпулом, продавайте що можете")18 book.sell(mint, 1.0, 0.0, "pool_gone")19 continue2021 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) * 10025 hours = (time.time() - s["opened"]) / 36002627 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}")3233 if m["liq_usd"] < s["liq0"] * (1 - EXIT["liq_drop_pct"] / 100):34 out(1.0, "liquidity_pulled"); continue35 if pct <= EXIT["stop_pct"]:36 out(1.0, "stop"); continue37 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 continue44 if s["steps"] > 0 and price <= s["peak"] * (1 - EXIT["trail_pct"] / 100):45 out(1.0, "trailing_stop"); continue46 if hours >= EXIT["time_stop_hours"] and pct < EXIT["time_stop_min_pct"]:47 out(1.0, "time_stop")48 return events4950if __name__ == "__main__":51 for e in watch():52 print(e)
1ЛІКВІДНІСТЬ ПЕРША. витягнутий пул б'є будь-яке інше правило, навіть якщо позиція в плюсі.2ТРЕЙЛІНГ АКТИВУЄТЬСЯ ПІСЛЯ ПЕРШОГО ТЕЙКУ. до цього -35% — єдина підлога.3МЕРТВІ ГРОШІ — ЦЕ ТЕЖ ЗБИТОК. шість годин без руху звільняють слот для наступного токена.4ТИША — ЦЕ СТАТУС. watch.py нічого не друкує, якщо нічого не змінилося, тому тихий чат означає, що туди не треба дивитися.

08. вивчіть 14 способів, якими гине токен
якби мені довелося викинути все вищесказане й залишити одну річ, це була б вона. вона також працює без жодного бота: пройдіть ті самі 14 перевірок вручну на rugcheck.xyz і dexscreener перед наступною покупкою, і ви пропустите більшість токенів, про які потім шкодували б.
13 перевірок — це код. порівняння, без моделі, без думок. 14-та — єдина, якій потрібен Grok.
#
перевірка
вбиває, коли
чому
1
вже рагнули
Rugcheck позначає його як rugged
хтось уже це зробив
2
право на емісію (mint authority)
досі відкрите
дев може надрукувати новий саплай прямо у ваш мішок
3
право на заморозку (freeze authority)
досі відкрите
дев може заморозити ваші токени, ви не зможете продати
4
прапорці небезпеки
будь-який ризик рівня danger
Rugcheck уже побачив те, що вам доведеться спростовувати
5
оцінка ризику
вище 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

09. дозвольте коду вбити очевидних
перевірки з 1 по 9. він тягне один звіт і залишає лише ті поля, які читає стіл. Grok ніколи не бачить сирий звіт: великий пейлоад коштує токенів і знижує точність.
одна деталь, яку люди пропускають: власне сховище пулу та локери сидять у списку топ-холдерів. порахуйте їх, і кожен токен виглядатиме як китовий. код відкидає їх, перш ніж підсумовувати топ-10.
1# rugcheck.py2# один звіт на токен, обрізаний до полів, які читає стіл. Grok ніколи не бачить сирий звіт.3import requests4from config import FACTS56RC = "https://api.rugcheck.xyz/v1/tokens"78def 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 {}1415 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")1819 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 026 risks = d.get("risks") or []2728 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 }4344def 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

10. перевіряйте пул, а не лише контракт
перевірки з 10 по 13. контракт може бути ідеальним, але пул усе одно не випустить вас. цей код читає найглибший пул для токена і ставить чотири нудні запитання: чи достатньо в ньому грошей, наскільки великий мій тікет порівняно з ним, скільки йому років і чи хтось взагалі продає.
1# market.py2# сам пул: глибина, вік, ціна і чи може хтось взагалі продати.3import time4import requests5from config import FACTS, TICKET_USD67DS = "https://api.dexscreener.com/tokens/v1/solana"89def 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 None17 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 }3031def 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:
1# grok.py2# єдиний файл, що містить ключ, і єдине місце, де термінал спілкується з xAI.3import os, json, datetime, requests4from config import MODEL56URL = "https://api.x.ai/v1/responses"78def _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 k1718def _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)2829def 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. це той файл, який ти насправді будеш перечитувати:
1# prompts.py2# єдиний промпт для Grok на терміналі. саме цей файл ти будеш перечитувати.34JUDGE_PROMPT = """5Ти — RUG DESK. Solana-мемкоїн щойно пройшов усі жорсткі перевірки в коді:6права доступу, LP, холдери, гаманець розробника, інсайдери, глибина пулу, вік.7Не перепровіряй ці цифри. Ти вирішуєш, чи заходить один фіксований тікет.8Ти ніколи не визначаєш розмір позиції й ніколи не обираєш точки виходу.910ВХІДНІ ДАНІ: {"token": {...факти з rugcheck...}, "pool": {...факти з dexscreener...}}1112КРОК 1. Пошукай у X тікер та адресу контракту за останні 72 години.13КРОК 2. Оцінюй лише те, чого код не бачить:14 - чи складаються ризики рівня warn у щось гірше разом15 - хто запостив першим: розробник, реальний акаунт з історією чи хвиля свіжих акаунтів16 - органічно чи куплено: однакові формулювання, однакова хвилина, акаунти без минулого17 - чи збігається адреса контракту в цих постах із тією, що у ВХІДНИХ ДАНИХ18 - чи був цей тікер або цей розробник раніше пов'язаний з рагпулом1920ПОВЕРТАЙ ЛИШЕ JSON:21{"verdict": "BUY" | "SKIP", "confidence": 0.0-1.0,22 "why": "максимум два рядки", "x_read": "один рядок про те, як виглядає X",23 "main_risk": "один рядок"}2425Нуль постів у X — це теж відповідь: ніхто не знає, що він існує. SKIP.26Інша адреса контракту під тим самим тікером у X: ризик копії. SKIP.27НІКОЛИ не відповідай BUY, якщо потрібне тобі поле дорівнює null.28НІКОЛИ не згадуй цільові ціни. Ти їх не знаєш.29"""
12. зв'яжи все в одну команду
одна адреса контракту на вході, один вердикт на виході. ліміти, факти, пул, Grok — саме в такому порядку, і перший, хто скаже «ні», все зупиняє:
1# check.py2# одна адреса контракту на вході, один вердикт на виході. запускається щоразу, коли токен потрапляє на твій термінал.3import csv, json, os, sys, time4from config import LOG, MIN_CONFIDENCE, PAPER, TICKET_USD5from rugcheck import report, fact_kill6from market import pool, market_kill7from grok import ask8from prompts import JUDGE_PROMPT9import book1011def 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})1920def check(mint: str) -> dict:21 if (g := book.guard(mint)): # ліміти, безкоштовно22 return {"stage": "limits", "verdict": "SKIP", "reason": g}2324 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"]}3031 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"]}3738 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}"}4243 verdict, conf = ans.get("verdict"), ans.get("confidence") or 044 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"]}4950if __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>", і він виконає один рядок. результат виглядатиме приблизно так (приклад структури, а не реальний токен):
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}

1ФАКТИ ПЕРЕДУЮТЬ ДУМКАМ. Grok ніколи не вирішує, чи відкритий мінт.2НЕВДАЛИЙ ВИКЛИК — ЦЕ SKIP. Rugcheck ліг, DexScreener ліг, Grok ліг, кривий JSON: SKIP.3NULL — ЦЕ НЕ ЧИСТО. поле, яке не повернулося, вбиває токен, а не пропускає його.4ОДИН ВЕРДИКТ НА ТОКЕН. ніколи не перезапускай, поки не побачиш BUY. якщо ти не згоден — ти не згоден із config.py.5ЧИТАЙ ПРИЧИНИ ВБИВСТВ, А НЕ ПОКУПОК. покупки тішать. причини відсіювання показують, чи працює фільтр.
13. три рутини, по одному реченню кожна
ніякого конструктора воркфлоу. ти один раз описуєш боту кожну рутину одним реченням, і він показує тобі наступний запуск. ось мої, слово в слово:
1Кожні 10 хвилин у /workspace/desk запускай python watch.py.2Якщо нічого не виводить — нічого не кажи. Якщо щось виводить — опублікуй це тут слово в слово.
1Кожні 30 хвилин у /workspace/desk запускай python scan.py.2Публікуй лише вердикти BUY: символ, впевненість, x_read.3Якщо Rugcheck або DexScreener лежить, скажи який саме один раз, а не при кожному запуску.
1Щодня о 21:30 у /workspace/desk запускай python report.py і публікуй результат тут.2Додай одну річ, яка сьогодні спрацювала, і одне значення в config.py, яке ти б поставив під сумнів, із поясненням чому.3Ніколи не змінюй це значення самостійно.
два файли, які запускають ці рутини. збережи як report.py:
1# report.py2# вечірній звіт. усе в ньому береться з checks.csv і trades.csv, нічого — з пам'яті.3import csv, os, time4from collections import Counter5from config import LOG, PAPER6import book78day = 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"]1213by_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"))1718print(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. оплачений профіль — не сигнал якості, це лише означає, що розробник витратив гроші. решту вирішує фільтр:
1# scan.py2# необов'язкове джерело лідів: свіжі токени Solana, які щойно оплатили профіль на DexScreener.3# оплачений профіль — не сигнал якості, це лише означає, що розробник витратив гроші. фільтр вирішує.4import csv, os, subprocess, sys5import requests6from config import LOG78seen = {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]1314for mint in fresh[:5]: # п'ять за запуск, щоб одна активна година не вичерпала ліміт API15 subprocess.run([sys.executable, "check.py", mint])
останнє на сьогодні: Settings, General, Auto-review. додай два правила Ask first — вони зупиняють дію і чекають на тебе незалежно від того, що думає будь-яка рутина:
1Спершу питай перед будь-яким підключенням гаманця, підписом, свопом або переказом.2Спершу питай перед редагуванням будь-якого файлу з назвою config.py.


14. тиждень на папері перед першим доларом
PAPER = True означає, що термінал робить усе по-справжньому, окрім грошей. реальні токени, реальні ціни, реальні виходи, фейкові виконання. через сім днів відкрий checks.csv і прочитай його так, ніби його написав незнайомець.
що шукати: яка перевірка вбиває найчастіше, чи купив би ти ті токени, що отримали BUY, і чи не виглядає хибною якась причина SKIP. паперове виконання відбувається за ціною на екрані, реальне — ніколи, тому сприймай паперовий результат як стелю, а не як прогноз.
коли перейдеш на лайв, зміни PAPER на False, і нічого не зміниться, окрім останнього кроку. check.py перестає купувати й натомість виводить рядок для підтвердження: купи $25 самостійно у своєму гаманці, а потім одна команда додасть це в книгу, щоб watch.py почав це охороняти.
коли все ламається
це стосується грошей, тому для кожного збою відповідь має бути записана ще до того, як він станеться.
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.
1cost_per_token = input_tokens / 1_000_000 * price_per_M_input2 + output_tokens / 1_000_000 * price_per_M_output3 + posts_fetched / 1_000 * 5 # пошук у X: $5 за 1000 знайдених постів45max_turns = 2 обмежує пошук двома раундами, тому posts_fetched залишається малим.6кожна відповідь звітує власне x_posts_fetched, тож перший же день покаже тобі реальну цифру.78ціна: [ціна з console.x.ai]
те, що люди розуміють неправильно: рахунок масштабується від кількості тих, хто вижив, а не від сканера. scan.py може подавати на термінал 240 токенів на день, і більшість із них гине безкоштовно ще до того, як Grok про них дізнається.

важлива частина
це мій сетап, а не твоя стратегія.
кожна цифра в config.py — моя, підібрана під тікет у $25 і мою власну готовність дивитися, як щось летить у нуль. більшість мемкоїнів справді летить у нуль, і більшість людей, які ними торгують, втрачають гроші. фільтр не робить токен хорошим. він прибирає очевидні способи втратити гроші й змушує тебе читати, чому помер кожен токен.
попрацюй тиждень на папері. читай причини відсіювання. змінюй цифри там, де не згоден, і тільки письмово. копіюй структуру, а не константи. це не фінансова порада.
код вбиває, Grok читає X, ти підписуєш. скрипт ніколи не приймає суб'єктивних рішень, Grok ніколи не отримує калькулятор, і ніхто, крім тебе, не торкається гаманця.
збережи це перед наступною покупкою. підписуйся, якщо плануєш запускати щось подібне, далі буде більше такого 🫶
мій tg - t.me/+8wAXS0nHWgA2MGEy
мій github - github.com/0xboan
торгуй тут - fomo.family/r/0xboan





