#!/usr/bin/env python3
"""SEEDS Breakout Bot - Price breakout above resistance"""
import time,json,os,sys,logging
from datetime import datetime
logging.basicConfig(level=logging.INFO,format='%(asctime)s [%(levelname)s] %(message)s',handlers=[logging.StreamHandler()])
log=logging.getLogger(__name__)
BOT_DIR=os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0,BOT_DIR)
TRADE_FILE=os.path.join(BOT_DIR,'breakout_trades.json')
CTRL_FILE=os.path.join(BOT_DIR,'bot_control.json')
COINS=[{'pair':'SOLUSD','coin':'SOL','capital':25.0},{'pair':'XXRPZUSD','coin':'XRP','capital':25.0},{'pair':'ADAUSD','coin':'ADA','capital':25.0},{'pair':'XETHZUSD','coin':'ETH','capital':25.0}]
LOOKBACK=20;BREAKOUT_PCT=0.005;TAKE_PROFIT=0.05;STOP_LOSS=0.025;INTERVAL=60
def load_state():
    try:
        if os.path.exists(TRADE_FILE):
            with open(TRADE_FILE) as f: return json.load(f)
    except: pass
    return {'trades':[],'total_profit':0.0,'positions':{}}
def save_state(s): open(TRADE_FILE,'w').write(json.dumps(s,indent=2))
def is_enabled():
    try:
        if os.path.exists(CTRL_FILE):
            with open(CTRL_FILE) as f: return json.load(f).get('breakout_enabled',True)
    except: pass
    return True
class BreakoutBot:
    def __init__(self,cfg,api):
        self.pair=cfg['pair'];self.coin=cfg['coin'];self.capital=cfg['capital']
        self.api=api;self.prices=[];self.volumes=[];self.position=None
        self.buy_price=0.0;self.volume=0.0;self.resistance=None
    def get_ticker(self):
        try:
            r=self.api.query_public('Ticker',{'pair':self.pair})
            if not r.get('error'):
                d=list(r['result'].values())[0]
                return float(d['c'][0]),float(d['v'][1]),float(d['h'][1])
        except: pass
        return None,None,None
    def update(self,state):
        price,volume,high=self.get_ticker()
        if not price: return
        self.prices.append(price);self.volumes.append(volume or 0)
        if len(self.prices)>LOOKBACK*2: self.prices=self.prices[-LOOKBACK*2:];self.volumes=self.volumes[-LOOKBACK*2:]
        if len(self.prices)>=LOOKBACK: self.resistance=max(self.prices[-LOOKBACK:-1]) if len(self.prices)>1 else price
        res_str=f'${self.resistance:.4f}' if self.resistance else 'building...'
        log.info(f'[{self.coin}] ${price:.4f} | Resistance: {res_str}')
        if self.position=='long':
            pnl=(price-self.buy_price)/self.buy_price
            log.info(f'[{self.coin}] P&L: {pnl*100:.2f}%')
            if pnl>=TAKE_PROFIT: self._sell(price,'take_profit',state)
            elif pnl<=-STOP_LOSS: self._sell(price,'stop_loss',state)
            return
        if self.resistance and self.position is None and len(self.prices)>=LOOKBACK:
            if price>self.resistance*(1+BREAKOUT_PCT):
                log.info(f'[{self.coin}] BREAKOUT above ${self.resistance:.4f}!')
                self._buy(price,state)
    def _buy(self,price,state):
        try:
            vol=round(self.capital/price,6)
            r=self.api.query_private('AddOrder',{'pair':self.pair,'type':'buy','ordertype':'market','volume':str(vol)})
            if r.get('error'): log.warning(f'Buy error: {r["error"]}'); return
            self.position='long';self.buy_price=price;self.volume=vol
            state['positions'][self.coin]={'active':True,'buy_price':price,'volume':vol,'resistance':self.resistance,'time':datetime.now().isoformat()}
            save_state(state);log.info(f'[{self.coin}] BREAKOUT BUY @ ${price:.4f}')
        except Exception as e: log.error(f'Error: {e}')
    def _sell(self,price,reason,state):
        try:
            r=self.api.query_private('AddOrder',{'pair':self.pair,'type':'sell','ordertype':'market','volume':str(self.volume)})
            if r.get('error'): log.warning(f'Sell error: {r["error"]}'); return
            net=(price-self.buy_price)*self.volume-(self.buy_price+price)*self.volume*0.0013
            state['total_profit']=round(state.get('total_profit',0)+net,4)
            state['trades'].append({'coin':self.coin,'buy_price':self.buy_price,'sell_price':price,'profit_usd':round(net,4),'reason':reason,'time':datetime.now().isoformat()})
            state['positions'][self.coin]={'active':False};save_state(state)
            self.position=None;log.info(f'[{self.coin}] BREAKOUT SELL @ ${price:.4f} | {reason} | Net: ${net:.4f}')
        except Exception as e: log.error(f'Error: {e}')
def main():
    import krakenex
    from config_advanced import API_KEY,API_SECRET
    api=krakenex.API(key=API_KEY,secret=API_SECRET)
    state=load_state();bots=[BreakoutBot(cfg,api) for cfg in COINS]
    for bot in bots:
        pos=state.get('positions',{}).get(bot.coin,{})
        if pos.get('active'): bot.position='long';bot.buy_price=pos.get('buy_price',0);bot.volume=pos.get('volume',0);bot.resistance=pos.get('resistance',0)
    log.info('='*60);log.info('SEEDS Breakout Bot | LIVE');log.info('='*60)
    cycle=0
    while True:
        try:
            if not is_enabled(): log.info('[Breakout] Disabled');time.sleep(60);continue
            cycle+=1;log.info(f'--- Breakout Cycle {cycle} | {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} ---')
            for bot in bots: bot.update(state);time.sleep(2)
            log.info(f'SUMMARY | P&L: ${state["total_profit"]:.4f} | Trades: {len(state["trades"])}')
            time.sleep(INTERVAL)
        except KeyboardInterrupt: break
        except Exception as e: log.error(f'Error: {e}');time.sleep(15)
if __name__=='__main__': main()
