첫 번째 커밋
This commit is contained in:
187
bot.py
Normal file
187
bot.py
Normal 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()
|
||||
|
||||
Reference in New Issue
Block a user