첫 번째 커밋

This commit is contained in:
javamon
2025-12-06 22:31:19 +09:00
commit 849a100fa9
33 changed files with 6613 additions and 0 deletions

187
bot.py Normal file
View File

@@ -0,0 +1,187 @@
# -*- coding: utf-8 -*-
from db import DB
from datetime import datetime, timedelta
import sys
from trader import Trader
# Email
from mail import Mail
''' 완료 항목
# Bot Table : 금융 아이디, 거래소 아이디, 아이템, 예상수익, 실제 수익, 예상 승률,
# 실제 승률, 거래수, 매매전략, 시간종류
# 봇 생성 조건
# 1. 시뮬레이팅 완료된 종목
# 2. 수익률 15프로 이상 / 승률 80프로 이상의 매매전략이 있을 경우만
# 봇 매매전략 업데이트
# 중지된 봇을 재 시뮬레이팅 후 최고 수익률로 전략 업데이트
# 봇 삭제 조건
# 거래수 5번이상 일 때, 실제 수익이 3퍼센트 미만일 경우 봇 상태값 N으로 변경 => 수익성 없음 판단
'''
''' 진행중 항목
# 포지션 존재 => 트레이더 객체를 통해 포지션이 있을 경우 포지션은 종료한다. => 트레이더 객체 구현 시 적용
'''
class Bot:
db = DB()
trader = Trader()
mail = Mail()
def send_email(self, title, msg):
self.mail.send_email(title, msg)
def run(self):
# 테이블 존재 체크
if not (self.db.is_table('bot') or self.db.is_table('simulation')):
return
print('Started. Bot Process')
# 2달 지난 시뮬레이터 기록 삭제
self._remove_simul_results_deadline()
# 거래소별 봇 생성 및 업데이트
for e in self.db.select_exchange_list_for_bot():
info = e['exchange_info']
# 시뮬레이팅이 완료된 종목만 실행
if not self.is_exchange_complete_sumulations(info):
continue
# 봇 생성 및 갱신
self._make_update_bots(info)
# 봇 생성 및 업데이트
# for i in self._get_trade_list():
# # 해당 거래소 시뮬레이팅 완료 체크
# self._make_update_bots(i)
# 수익이 저조한 봇 중지
for bot in self.get_running_bots():
self._check_bot_profit_and_stop(bot)
# 초기 시드 갱신
# self.update_seed_data_in_bot(bot)
print('Ended. Bot Process')
def is_exchange_complete_sumulations(self, exchange_info):
# i = info['job'].split('/')
# ex = '_'.join(i[:-2])
job_info = self.db.select_tb_cron_simul_status(exchange_info)
for s in job_info:
if s['init_simul'] == 'N':
return False
return True
def update_seed_data_in_bot(self, bot):
deadline_date = datetime.now() - timedelta(weeks=5)
if bot['update_date'] < deadline_date:
updated_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.db.update_first_seed_by_now_seed(bot, updated_date)
def _remove_simul_results_deadline(self):
deadline_date = datetime.now() - timedelta(weeks=10)
self.db.delete_simul_results_by_deadline(deadline_date)
# 트레이더 객체를 통해 해당 봇의 포지션을 종료한다.
def _close_bot_position(self, bot_info):
if bot_info['position'] != 'None':
self.trader.force_close_position(bot_info)
def _check_bot_profit_and_stop(self, bot):
if int(bot['trade_cnt']) >= 6 and float(bot['profit']) < -1 or float(bot['last_profit']) <= -2:
self._close_bot_position(bot)
self._stop_bot_by_id(bot['id'])
self._init_simul_status(bot['target'])
title = '[%s] %s mode - 해당 거래소 봇이 수익 미달로 중지되었습니다' % (bot['target'], bot['mode'])
body = "\n".join('{} : {}'.format(key, value) for key, value in bot.items())
self.send_email(title, body)
def _stop_bot_by_id(self, bot_id):
self.db.update_bot_data_for_stop_by_id(bot_id)
def _init_simul_status(self, target):
t = str(target).split('_')
i = '/'.join(t[:-1])
self.db.update_tb_cron_simul_status(i)
def get_running_bots(self):
return self.db.select_running_bots()
def _make_update_bots(self, e_info):
# s_item = t_item['job'].split('/')
# e_i = self.db.get_id_by_exchange_name(s_item[1])
res = self._get_satisfy_condition_result_row(e_info)
if res:
self._upsert_bot_data(res)
def _upsert_bot_data(self, this_bot):
item = this_bot['t_table_name'].split('_')
target = '_'.join(item[:-1])
this_bot['target'] = target
prev_bot = self.db.get_bot_data_by_target(target)
return self.compare_prev_bot_and_new_bot(prev_bot, this_bot)
def compare_prev_bot_and_new_bot(self, prev_bot, this_bot):
# 수익률이 없다고 판단 될 시 봇 생성 거부
if float(this_bot['profit_rate']) < 15:
return False
# 봇이 없을 경우 새로운 봇 생성
if prev_bot is ():
title = '[%s] - 해당 거래소 봇이 생성되었습니다.' % (this_bot['target'])
body = "\n".join('{} : {}'.format(key, value) for key, value in this_bot.items())
self.send_email(title, body)
return self.db.upsert_bot_data(this_bot)
# 현재 봇이 최신 봇일 경우
if prev_bot['strategy'] == this_bot['used_patterns']:
return False
# 봇이 중지 상태이고, 이전 전략과 다를 경우 갱신
if str(prev_bot['status']) == 'N' and \
str(prev_bot['strategy']).replace('"', '') != str(this_bot['used_patterns']).replace('"', ''):
title = '[%s] - 해당 거래소 봇이 갱신되었습니다.' % (this_bot['target'])
body = "\n".join('{} : {}'.format(key, value) for key, value in this_bot.items())
self.send_email(title, body)
return self.db.upsert_bot_data(this_bot)
# 비교 로직(수익률/승률 비교)
# if float(this_bot['profit_rate']) > float(prev_bot['p_profit']) and \
# float(this_bot['win_rate']) >= float(prev_bot['p_winrate']):
# return self.db.upsert_bot_data(this_bot)
# 시뮬레이션 결과 중 조건에 만족하는 데이터 가져오기
def _get_satisfy_condition_result_row(self, t_name):
res = self.db.get_simul_res_top_row(t_name.replace('/', '_'))
if res is ():
return False
return res
def _get_trade_list(self):
return self.db.get_completed_simul_list()
if __name__ == "__main__":
b = Bot()
b.run()