IT와 보안 그 어디 쯤/웹프로그래밍_끄적이기

코인자동매매 프로그램 - 업비트 용. 텔레그램봇 - 테스트용

깊음위에 2024. 8. 18. 02:39
반응형
import os
import pyupbit
import time
import pandas as pd
import asyncio
from dotenv import load_dotenv
from telegram import Update
from telegram.ext import Updater, CommandHandler, CallbackContext, Application

# Load API keys from .env file
load_dotenv(dotenv_path='config.env')
UPBIT_ACCESS_KEY = os.getenv('UPBIT_ACCESS_KEY')
UPBIT_SECRET_KEY = os.getenv('UPBIT_SECRET_KEY')
TELEGRAM_TOKEN = os.getenv('TELEGRAM_TOKEN')

# Initialize Upbit and Telegram
upbit = pyupbit.Upbit(UPBIT_ACCESS_KEY, UPBIT_SECRET_KEY)
application = Application.builder().token(TELEGRAM_TOKEN).build()

# Global variables
selected_coin = None
is_trading = False
trade_task = None

def check_volume_increase(df, minutes):
    """거래량 연속 증가 확인"""
    return all(df['volume'].diff().iloc[-minutes:] > 0)

def check_price_increase(df, minutes):
    """가격 연속 증가 확인"""
    return all(df['close'].diff().iloc[-minutes:] > 0)

def check_volume_increase_percentage(df, minutes, threshold):
    """거래량 증가율 확인"""
    volume_increase = (df['volume'].iloc[-1] / df['volume'].iloc[-minutes] - 1) * 100
    return volume_increase > threshold

# Command handlers
async def start(update: Update, context: CallbackContext) -> None:
    await update.message.reply_text('코인 자동 거래 봇이 시작되었습니다!')
    await context.bot.send_message(chat_id=update.effective_chat.id, text="코인 자동 거래 봇이 실행되었습니다!")

async def select_coin(update: Update, context: CallbackContext) -> None:
    global selected_coin
    if not context.args:
        await update.message.reply_text('코인을 선택하려면 /select_coin [코인심볼] 형식으로 입력하세요.')
        await context.bot.send_message(chat_id=update.effective_chat.id, text='코인을 선택하려면 /select_coin [코인심볼] 형식으로 입력하세요.')
    else:
        selected_coin = context.args[0]
        await update.message.reply_text(f'선택된 코인: {selected_coin}')
        await context.bot.send_message(chat_id=update.effective_chat.id, text=f'선택된 코인: {selected_coin}')

async def start_trading(update: Update, context: CallbackContext) -> None:
    global is_trading, trade_task
    is_trading = True
    await update.message.reply_text('자동 거래가 시작되었습니다!')
    await context.bot.send_message(chat_id=update.effective_chat.id, text="자동 거래가 시작되었습니다!")
    trade_task = asyncio.create_task(trade(update, context))

async def stop_trading(update: Update, context: CallbackContext) -> None:
    global is_trading, trade_task
    is_trading = False
    if trade_task:
        trade_task.cancel()
    await update.message.reply_text('자동 거래가 종료되었습니다!')
    await context.bot.send_message(chat_id=update.effective_chat.id, text="자동 거래가 종료되었습니다!")

async def check_balance(update: Update, context: CallbackContext) -> None:
    balance = upbit.get_balance()
    await update.message.reply_text(f'잔고: {balance} 원')
    await context.bot.send_message(chat_id=update.effective_chat.id, text=f'잔고: {balance} 원')

import logging

# 로깅 설정
logging.basicConfig(filename='trading_bot.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
import os
import pyupbit
import time
import pandas as pd
import asyncio
from dotenv import load_dotenv
from telegram import Update
from telegram.ext import Updater, CommandHandler, CallbackContext, Application

# Load API keys from .env file
load_dotenv(dotenv_path='config.env')
UPBIT_ACCESS_KEY = os.getenv('UPBIT_ACCESS_KEY')
UPBIT_SECRET_KEY = os.getenv('UPBIT_SECRET_KEY')
TELEGRAM_TOKEN = os.getenv('TELEGRAM_TOKEN')

# Initialize Upbit and Telegram
upbit = pyupbit.Upbit(UPBIT_ACCESS_KEY, UPBIT_SECRET_KEY)
application = Application.builder().token(TELEGRAM_TOKEN).build()

# Global variables
selected_coin = None
is_trading = False
trade_task = None

def check_volume_increase(df, minutes):
    """거래량 연속 증가 확인"""
    return all(df['volume'].diff().iloc[-minutes:] > 0)

def check_price_increase(df, minutes):
    """가격 연속 증가 확인"""
    return all(df['close'].diff().iloc[-minutes:] > 0)

def check_volume_increase_percentage(df, minutes, threshold):
    """거래량 증가율 확인"""
    volume_increase = (df['volume'].iloc[-1] / df['volume'].iloc[-minutes] - 1) * 100
    return volume_increase > threshold

# Command handlers
async def start(update: Update, context: CallbackContext) -> None:
    await update.message.reply_text('코인 자동 거래 봇이 시작되었습니다!')
    await context.bot.send_message(chat_id=update.effective_chat.id, text="코인 자동 거래 봇이 실행되었습니다!")

async def select_coin(update: Update, context: CallbackContext) -> None:
    global selected_coin
    if not context.args:
        await update.message.reply_text('코인을 선택하려면 /select_coin [코인심볼] 형식으로 입력하세요.')
        await context.bot.send_message(chat_id=update.effective_chat.id, text='코인을 선택하려면 /select_coin [코인심볼] 형식으로 입력하세요.')
    else:
        selected_coin = context.args[0]
        await update.message.reply_text(f'선택된 코인: {selected_coin}')
        await context.bot.send_message(chat_id=update.effective_chat.id, text=f'선택된 코인: {selected_coin}')

async def start_trading(update: Update, context: CallbackContext) -> None:
    global is_trading, trade_task
    is_trading = True
    await update.message.reply_text('자동 거래가 시작되었습니다!')
    await context.bot.send_message(chat_id=update.effective_chat.id, text="자동 거래가 시작되었습니다!")
    trade_task = asyncio.create_task(trade(update, context))

async def stop_trading(update: Update, context: CallbackContext) -> None:
    global is_trading, trade_task
    is_trading = False
    if trade_task:
        trade_task.cancel()
    await update.message.reply_text('자동 거래가 종료되었습니다!')
    await context.bot.send_message(chat_id=update.effective_chat.id, text="자동 거래가 종료되었습니다!")

async def check_balance(update: Update, context: CallbackContext) -> None:
    balance = upbit.get_balance()
    await update.message.reply_text(f'잔고: {balance} 원')
    await context.bot.send_message(chat_id=update.effective_chat.id, text=f'잔고: {balance} 원')

import logging

# 로깅 설정
logging.basicConfig(filename='trading_bot.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
async def trade(update: Update, context: CallbackContext):
    global is_trading
    buy_price = None
    stop_loss = 0.95
    take_profit = 1.10

    while is_trading:
        try:
            df = pyupbit.get_ohlcv(selected_coin, interval="minute5", count=200)
            if df is None:
                raise ValueError("데이터를 가져오지 못했습니다. 코인 심볼을 확인하세요.")

            short_ma = df['close'].rolling(window=5).mean()
            long_ma = df['close'].rolling(window=20).mean()

            krw_balance = upbit.get_balance("KRW")
            if isinstance(krw_balance, dict):
                krw_balance = float(krw_balance['balance'])

            coin_balance = upbit.get_balance(selected_coin)
            if isinstance(coin_balance, dict):
                coin_balance = float(coin_balance['balance'])

            # 단순 매수 신호 조건
            if short_ma[-1] > long_ma[-1] and short_ma[-2] <= long_ma[-2] and coin_balance == 0:
                buy_price = upbit.buy_market_order(selected_coin, krw_balance * 0.9995)
                logging.info(f"매수 신호 발생 - 매수 주문 실행: {buy_price}")
                await context.bot.send_message(chat_id=update.effective_chat.id, text="매수 신호 발생 - 매수 주문 실행")

            elif check_price_increase(df, 10) and coin_balance == 0:
                buy_price = upbit.buy_market_order(selected_coin, krw_balance * 0.9995)
                logging.info(f"거래량 및 가격 증가 - 매수 주문 실행: {buy_price}")

            if coin_balance > 0:
                current_price = df['close'][-1]
                # 손절매 및 이익 실현 비율 동적 조정
                if current_price <= buy_price * stop_loss:
                    upbit.sell_market_order(selected_coin, coin_balance)
                    logging.info(f"손절매 - 매도 주문 실행: {current_price}")
                    await context.bot.send_message(chat_id=update.effective_chat.id, text="손절매 - 매도 주문 실행")
                    buy_price = None
                elif current_price >= buy_price * take_profit:
                    upbit.sell_market_order(selected_coin, coin_balance)
                    logging.info(f"이익 실현 - 매도 주문 실행: {current_price}")
                    await context.bot.send_message(chat_id=update.effective_chat.id, text="이익 실현 - 매도 주문 실행")
                    buy_price = None

            # asyncio.sleep을 사용하여 주기적으로 is_trading 상태 확인
            await asyncio.sleep(300)  # 5분 동안 대기
        except asyncio.CancelledError:
            logging.info("자동 거래가 취소되었습니다.")
            await context.bot.send_message(chat_id=update.effective_chat.id, text="자동 거래가 취소되었습니다.")
            break
        except Exception as e:
            logging.error(f"오류 발생: {e}")
            await context.bot.send_message(chat_id=update.effective_chat.id, text=f"오류 발생: {e}")
            await asyncio.sleep(60)


# Add handlers to dispatcher
application.add_handler(CommandHandler('start', start))
application.add_handler(CommandHandler('select_coin', select_coin))
application.add_handler(CommandHandler('start_trading', start_trading))
application.add_handler(CommandHandler('stop_trading', stop_trading))
application.add_handler(CommandHandler('check_balance', check_balance))

# Start the bot
application.run_polling()


# Add handlers to dispatcher
application.add_handler(CommandHandler('start', start))
application.add_handler(CommandHandler('select_coin', select_coin))
application.add_handler(CommandHandler('start_trading', start_trading))
application.add_handler(CommandHandler('stop_trading', stop_trading))
application.add_handler(CommandHandler('check_balance', check_balance))

# Start the bot
application.run_polling()

텔레그램과 연동했습니다.

이 코드는 Upbit 거래소에서 자동으로 코인을 거래하는 Telegram 봇을 구현한 것입니다. 아래는 코드 분석과 사용법입니다.

코드 분석

1. 라이브러리 임포트

  • os: 환경 변수 접근을 위한 모듈.
  • pyupbit: Upbit API를 사용하기 위한 라이브러리.
  • time, pandas, asyncio: 시간, 데이터 처리, 비동기 작업을 위한 모듈.
  • dotenv: .env 파일에서 환경 변수를 로드하기 위한 모듈.
  • telegram: Telegram 봇 API를 사용하기 위한 모듈.
  • logging: 로그 기록을 위한 모듈.

2. 환경 변수 로드

  • load_dotenv: API 키와 토큰을 포함한 환경 변수를 로드합니다.
  • UPBIT_ACCESS_KEY, UPBIT_SECRET_KEY, TELEGRAM_TOKEN: Upbit API와 Telegram Bot API에 필요한 키.

3. Upbit 및 Telegram 초기화

  • upbit: Upbit API 객체 생성.
  • application: Telegram 봇 객체 생성.

4. 글로벌 변수

  • selected_coin: 선택된 코인 심볼.
  • is_trading: 거래 상태를 나타내는 플래그.
  • trade_task: 비동기 거래 작업을 위한 변수.

5. 거래 조건 확인 함수

  • check_volume_increase: 거래량이 연속적으로 증가하는지 확인.
  • check_price_increase: 가격이 연속적으로 증가하는지 확인.
  • check_volume_increase_percentage: 거래량 증가율을 확인.

6. 명령어 핸들러

  • start: 봇 시작 메시지 전송.
  • select_coin: 코인 선택 및 확인.
  • start_trading: 자동 거래 시작.
  • stop_trading: 자동 거래 중지.
  • check_balance: 현재 잔고 확인.

7. 거래 로직

  • trade: 선택된 코인에 대해 매수 및 매도 로직을 수행.
    • 이동 평균을 사용하여 매수 신호를 감지.
    • 손절매 및 이익 실현 조건을 설정.

8. 로깅

  • 모든 거래 및 오류 정보를 trading_bot.log 파일에 기록.

9. 핸들러 추가 및 봇 시작

  • Telegram 봇에 명령어 핸들러를 추가하고, 폴링 방식으로 봇을 실행.

사용법

  1. 환경 설정
    • .env 파일을 생성하고 다음과 같이 API 키를 추가합니다.
      UPBIT_ACCESS_KEY=your_upbit_access_key
      UPBIT_SECRET_KEY=your_upbit_secret_key
      TELEGRAM_TOKEN=your_telegram_bot_token
  2. 봇 실행
    • Python 환경에서 이 코드를 실행합니다.
  3. Telegram 명령어 사용
    • /start: 봇을 시작합니다.
    • /select_coin [코인심볼]: 거래할 코인을 선택합니다. 예: /select_coin BTC.
    • /start_trading: 자동 거래를 시작합니다.
    • /stop_trading: 자동 거래를 중지합니다.
    • /check_balance: 현재 잔고를 확인합니다.
  4. 로그 확인
    • 거래 및 오류 정보는 trading_bot.log 파일에서 확인할 수 있습니다.

***** 이 프로그램은 충분한 테스트를 거치지 않았습니다.  이 프로그램으로 인한 손실에 대해서는 각자 알아서 하세요. 테스트용 개발용으로 올립니다 **********

반응형