Path: blob/master/ invest-robot-contest_sirius-master/strategy/robot_thread.py
5932 views
import logging1import time2import traceback34from api_calls.get_info import get_candles_by_figi5from services.account_info import has_enough_money6from services.history_test_data import test_get_candles_by_date, get_test_current_date, get_next_test_current_date7from services.instruments_info_cache import make_instrument_key, get_instrument_info_by_key8from services.trading_info import get_trading_info_for_key, save_trading_info9from strategy.buy_sell_utils import sell, buy10from strategy.calculate_utils import calc_profit_percent, add_prices_to_candles11from strategy.trade_signal import get_trade_signal12from utils.datetime_utils import current_date, string_to_date, date_minus_minutes13from utils.settings import settings141516# отдельный торговый поток. Возможно, следует иметь по одному отдельному потоку на каждый инструмент торговли.1718def get_candles(instrument_info, last_processed_date):19if settings()['MAIN']['mode'] == 'history_test':20exchange = instrument_info['exchange']21ticker = instrument_info['ticker']22return test_get_candles_by_date(exchange, ticker, last_processed_date.timestamp(),23get_current_date().timestamp())24elif settings()['MAIN']['mode'] == 'sandbox':25return get_candles_by_figi(instrument_info['figi'], last_processed_date, get_current_date(),26'CANDLE_INTERVAL_1_MIN')['candles']27return None2829# TODO take profit/stop loss вынести в trade_signal30def process_instrument(account_info, instrument, trading_info, last_processed_date):31instrument_key = make_instrument_key(instrument['exchange'], instrument['ticker'])32instrument_info = get_instrument_info_by_key(instrument_key)3334instrument_trading_info = get_trading_info_for_key(instrument_key, trading_info)35has_share = instrument_trading_info['has_share']3637candles = get_candles(instrument_info, last_processed_date)38candles = add_prices_to_candles(candles)3940if len(candles) == 0:41return4243last_candle = candles[-1]44last_price = last_candle['price']4546# May be take profit or stop loss47if has_share:48profit_percent = calc_profit_percent(last_price, instrument_trading_info['last_buy_price'])49sell_reason = ''50if profit_percent > float(settings()['TRADE']['take_profit_percent']):51sell_reason = 'take_profit'52elif profit_percent < -float(settings()['TRADE']['stop_loss_percent']):53sell_reason = 'stop_loss'5455if sell_reason:56do_sell(account_info, instrument_info, instrument_trading_info, candles, sell_reason)57return5859signal = get_trade_signal(candles)6061if has_share:62if signal == 'sell':63do_sell(account_info, instrument_info, instrument_trading_info, candles, 'signal')64else:65if signal == 'buy':66do_buy(account_info, instrument_info, instrument_trading_info, candles)676869def do_buy(account_info, instrument_info, instrument_trading_info, candles):70deal_result = buy(account_info, instrument_info, candles)71if deal_result is None:72return7374instrument_trading_info['has_share'] = True75instrument_trading_info['last_buy_price'] = deal_result['price']7677instrument_trading_info['buy_count'] = instrument_trading_info['buy_count'] + 178instrument_trading_info['balance'] = instrument_trading_info['balance'] - \79deal_result['deal_price'] - deal_result['commission']8081logging.info("{} buy, price = {} {} {}"82.format(instrument_info['ticker'], deal_result['deal_price'],83instrument_info['currency'], deal_result['datetime']))848586def do_sell(account_info, instrument_info, instrument_trading_info, candles, reason):87deal_result = sell(account_info, instrument_info, candles)88if deal_result is None:89return9091profit_percent = calc_profit_percent(deal_result['price'], instrument_trading_info['last_buy_price'])9293instrument_trading_info['has_share'] = False94instrument_trading_info['last_buy_price'] = 09596instrument_trading_info['sell_count'] = instrument_trading_info['sell_count'] + 197instrument_trading_info['balance'] = instrument_trading_info['balance'] + \98deal_result['deal_price'] - deal_result['commission']99100logging.info("{} sell {}, price = {} {} profit_percent = {} {}"101.format(instrument_info['ticker'], reason, deal_result['deal_price'],102instrument_info['currency'], round(profit_percent, 2), deal_result['datetime']))103104105def get_current_date():106if settings()['MAIN']['mode'] == 'history_test':107return get_test_current_date()108else:109return current_date()110111112def is_time_to_process(last_processed_date, current_date, poll_interval_minutes):113return (current_date - last_processed_date).total_seconds() >= poll_interval_minutes * 60114115116def start_robot_thread(account_info, trading_info, instruments, should_stop_callback):117logging.info("Robot thread started")118119poll_interval_minutes = int(settings()['TRADE']['poll_interval_minutes'])120121if settings()['MAIN']['mode'] == 'history_test':122last_processed_date = get_current_date()123else:124cur_date = get_current_date()125if trading_info['last_processed_date'] is not None:126last_processed_date = string_to_date(trading_info['last_processed_date'])127if is_time_to_process(last_processed_date, cur_date, poll_interval_minutes):128last_processed_date = date_minus_minutes(cur_date, poll_interval_minutes)129else:130last_processed_date = date_minus_minutes(current_date(), poll_interval_minutes)131132while not should_stop_callback():133134try:135cur_date = get_current_date()136137if is_time_to_process(last_processed_date, cur_date, poll_interval_minutes):138if settings()['MAIN']['mode'] != 'history_test':139logging.info("Processing instruments")140if has_enough_money(account_info):141for instrument in instruments:142process_instrument(account_info, instrument, trading_info, last_processed_date)143else:144logging.warning("Processing skipped. Robot will not trade until it will have enough money")145last_processed_date = cur_date146trading_info['last_processed_date'] = str(last_processed_date)147148if settings()['MAIN']['mode'] != 'history_test':149save_trading_info(trading_info)150151if settings()['MAIN']['mode'] == 'history_test':152get_next_test_current_date()153else:154time.sleep(1)155except Exception as ex:156logging.error("Unexpected exception {}".format(ex))157traceback.print_exc()158time.sleep(10)159160logging.info("Robot thread finished, enter any command to exit")161162163