RAPTOR v18.4: Исправлена отчетность, активированы выходные

This commit is contained in:
root
2026-04-18 23:26:45 +03:00
commit ef0958239e
312 changed files with 54247 additions and 0 deletions

106
bot.py Normal file
View File

@@ -0,0 +1,106 @@
import time, os, requests, json, urllib3
from datetime import datetime, timedelta, timezone, time as dtime
from dotenv import load_dotenv
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
load_dotenv("tok.env")
TOKEN = os.getenv("TINKOFF_TOKEN")
TG_TOKEN = os.getenv("TG_TOKEN")
TG_CHAT_ID = os.getenv("TG_CHAT_ID")
ACC_ID = os.getenv("ACCOUNT_ID")
INSTRUMENT_UID = "a78b8349-a1dc-447d-9277-1d75826d089a"
BASE_URL = "https://invest-public-api.tbank.ru/rest"
STATE_FILE = "bot_state_prod.json"
s = requests.Session()
s.headers.update({"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"})
def get_price():
path = f"{BASE_URL}/tinkoff.public.invest.api.contract.v1.MarketDataService/GetLastPrices"
try:
r = s.post(path, json={"instrumentId": [INSTRUMENT_UID]}, timeout=5)
if r.status_code != 200: return None
res = r.json()
if 'lastPrices' in res and res['lastPrices']:
p = res['lastPrices'][0]['price']
return int(p.get('units', 0)) + int(p.get('nano', 0)) / 1e9
except: return None
return None
def get_atr_steps():
path = f"{BASE_URL}/tinkoff.public.invest.api.contract.v1.MarketDataService/GetCandles"
try:
now_utc = datetime.now(timezone.utc)
payload = {
"instrumentId": INSTRUMENT_UID,
"from": (now_utc - timedelta(days=2)).strftime('%Y-%m-%dT%H:%M:%SZ'),
"to": now_utc.strftime('%Y-%m-%dT%H:%M:%SZ'),
"interval": "CANDLE_INTERVAL_HOUR"
}
r = s.post(path, json=payload, timeout=10)
candles = r.json().get('candles', [])
if len(candles) < 2: return 1.1, 1.5
def to_f(p): return int(p.get('units', 0)) + int(p.get('nano', 0)) / 1e9
trs = [to_f(c['high']) - to_f(c['low']) for c in candles[-14:]]
atr = sum(trs) / len(trs)
buy_step = max(round(atr * 0.45, 2), 0.5)
return buy_step, round(buy_step * 1.2, 2)
except: return 1.1, 1.5
def post_order(direction):
path = f"{BASE_URL}/tinkoff.public.invest.api.contract.v1.OrdersService/PostOrder"
payload = {
"instrumentId": INSTRUMENT_UID, "quantity": 1,
"direction": direction, "orderType": "ORDER_TYPE_MARKET",
"accountId": ACC_ID, "orderId": f"p_{int(time.time())}"
}
try:
r = s.post(path, json=payload, timeout=10)
return r.status_code == 200
except: return False
def run():
print("🚀 БОТ ЗАПУЩЕН")
state = {"phase": "BUY", "base_price": None}
if os.path.exists(STATE_FILE):
try:
with open(STATE_FILE, 'r') as f: state = json.load(f)
except: pass
buy_step, profit_step = get_atr_steps()
while True:
price = get_price()
if price:
if state['base_price'] is None:
state['base_price'] = price
with open(STATE_FILE, 'w') as f: json.dump(state, f)
print(f"\n🎯 База установлена: {price}")
if state['phase'] == "BUY":
target = round(state['base_price'] - buy_step, 2)
else:
target = round(state['base_price'] + profit_step, 2)
print(f"[{datetime.now().strftime('%H:%M:%S')}] Цена: {price:.2f} | Цель: {target:.2f} | {state['phase']} ", end='\r')
if state['phase'] == "BUY" and price <= target:
if post_order("ORDER_DIRECTION_BUY"):
state.update({"phase": "SELL", "base_price": price})
with open(STATE_FILE, 'w') as f: json.dump(state, f)
print(f"\n🛒 КУПЛЕНО по {price}")
elif state['phase'] == "SELL" and price >= target:
if post_order("ORDER_DIRECTION_SELL"):
state.update({"phase": "BUY", "base_price": price})
with open(STATE_FILE, 'w') as f: json.dump(state, f)
print(f"\n💰 ПРОДАНО по {price}")
time.sleep(1)
if __name__ == "__main__":
run()