def setUp(self): print('api_key: ', end="") api_key = '' print('api_secret: ', end="") api_secret = '' self.api_gateway = ApiGateway(api_key=api_key, api_secret=api_secret) self.order_id = None
def __init__(self, pair='xrp_jpy', candle_type='15min', buying_price=None, limit=None, init_max_high=None, init_min_low=None): self.__pair = pair self.__candle_type = candle_type self.__api_gateway = ApiGateway() self.rsi_data = None self.rsi_step = None self.max_high = None self.min_low = None self.price = None self.trend = None # 設定 self.buy_deviation = 0.03 self.sell_deviation = 0.02 self.rsi_term = 14 self.rsi_bottom = 40.0 self.rsi_top = 60.0 self.__line = Line() self.buying_price = buying_price self.limit = limit self.decision_term = 0 self.candlestick = self.make_price_data_frame() self.init_max_high = init_max_high self.init_min_low = init_min_low self()
def __init__(self, short_term=12, long_term=26, signal=9, pair='xrp_jpy', candle_type='5min'): self.__short_term = short_term self.__long_term = long_term self.__signal = signal self.__pair = pair self.__candle_type = candle_type self.__api_gateway = ApiGateway() self.df_signal = None self.make_data_frame() self.trend_15min = None self.trend_5min = None self.area_15min = list() self.area_5min = list() self.max_histogram_5min = 0 self.max_histogram_15min = 0 self.start_macd_15min = None self.start_macd_5min = None self.start_signal_15min = None self.start_signal_5min = None self.mount_15min = None self.mount_5min = None self.count_15min = 1 self.count_5min = 1 self.is_plus_start_15min = None self.is_plus_start_5min = None self.max_price = None self.recognize()
class Adviser(ABC): BUY = 1 STAY = 2 SELL = 3 RETRY = 4 BUY_TYPE = 'buy' SELL_TYPE = 'sell' DEFAULT_TYPE = 'market' TYPE_LIMIT = 'limit' TYPE_MARKET = 'market' def __init__(self, pair='xrp_jpy', candle_type='15min', buying_price=None): self.api_gateway = ApiGateway() self.pair = pair self.candle_type = candle_type self.buying_price = buying_price self.candlestick = self.make_price_data_frame() @abstractmethod def operation(self, has_coin, is_waiting, buying_price, waiting_price, price=None): """ 指示と取引価格を渡す。 :param has_coin: bool :param price: None|float :param is_waiting: bool :param buying_price: float|None :param waiting_price: :return: const int, float """ pass def make_price_data_frame(self): """ 直近のロウソク足データ(2日分)から終値のデータフレームを作る :return: pandas.DataFrame 2日分のロウソク足データ """ today = datetime.datetime.now(timezone('UTC')) yesterday = today - datetime.timedelta(days=1) today = today.astimezone(timezone('Asia/Tokyo')) yesterday = yesterday.astimezone(timezone('Asia/Tokyo')) candlestick_today = self.api_gateway.use_candlestick( time=today.strftime("%Y%m%d"), candle_type=self.candle_type, pair=self.pair )['candlestick'][0]['ohlcv'] candlestick_yesterday = self.api_gateway.use_candlestick( time=yesterday.strftime('%Y%m%d'), candle_type=self.candle_type, pair=self.pair )['candlestick'][0]['ohlcv'] for item in candlestick_today: candlestick_yesterday.append(item) loc = datetime.datetime.fromtimestamp(int(candlestick_yesterday[-1][5]) / 1000) print('last: ', loc) return pd.DataFrame(candlestick_yesterday, columns=['open', 'high', 'low', 'end', 'yield', 'time'])
def __init__(self, adviser, pair, log): """ :param adviser: bitbank.adviser テクニカル分析結果から売却の指示をするクラスのインスタンス :param pair: string 通貨のペア :param log: """ super().__init__(adviser=adviser, pair=pair) self.order_id = 0 self.has_coin = False self.is_waiting = False self.waiting_price = None self.log = log self.api_gateway = ApiGateway()
def __init__(self, adviser, pair, api_key=None, api_secret=None): """ :param adviser: bitbank.adviser テクニカル分析結果から売却の指示をするクラスのインスタンス :param pair: string 通貨のペア :param api_key: :param api_secret: """ self.adviser = adviser self.pair = pair self.coin = pair.split('_')[0] self.yen = pair.split('_')[1] self.api_gateway = ApiGateway(api_key=api_key, api_secret=api_secret) self.buying_price = None self.order_ids = None self.__line = Line() self.__start_price = self.fetch_price()
def __init__(self, stock_term, inclination_alpha, pair, candle_type='5min'): self.__recent_data = None self.__recent_sma = None self.__recent_sigma = None self.__volatility = None self.__last_location = None self.__pre_location = None self.__inclination_pattern = None self.__stock_term = stock_term self.__inclination_alpha = inclination_alpha self.__pair = pair self.__candle_type = candle_type self.__api_gateway = ApiGateway() self.__initialize()
def __init__(self, pair='xrp_jpy', candle_type='15min', buying_price=None): self.api_gateway = ApiGateway() self.pair = pair self.candle_type = candle_type self.buying_price = buying_price self.candlestick = self.make_price_data_frame()
class Prototype(Auto): DIVIDE_ORDER = 1 PRICE_LIMIT = 3.0 COMMISSION = 0.0015 LOSS_CUT_PRICE = 0.5 BUY_FAIL = 0.02 SELL_FAIL = 0.02 def __init__(self, adviser, pair, log): """ :param adviser: bitbank.adviser テクニカル分析結果から売却の指示をするクラスのインスタンス :param pair: string 通貨のペア :param log: """ super().__init__(adviser=adviser, pair=pair) self.order_id = 0 self.has_coin = False self.is_waiting = False self.waiting_price = None self.log = log self.api_gateway = ApiGateway() def __call__(self): # 要求を確認 self.check_request() # 指示を受ける operation, price, order_type = self.adviser.operation( has_coin=self.has_coin, is_waiting=self.is_waiting, buying_price=self.buying_price, waiting_price=self.waiting_price) self.request(operation=operation, price=price, order_type=order_type) def request(self, operation, price, order_type): if operation == int(self.BUY): line_ = 'BUY : {:<10}'.format(price) + now() + '\n' over_write_file(directory=self.log, line_=line_) self.buy(price=price, amount='hoge', order_type=order_type) elif operation == int(self.SELL): line_ = 'SELL : {:<10}'.format(price) + now() + '\n' over_write_file(directory=self.log, line_=line_) self.sell(price=price, amount='hoge', order_type=order_type) elif operation == int(self.RETRY): # キャンセル result = self.cancel_orders(order_id=self.order_id) # 再要求 if result.side == 'buy': line_ = 'RETRY BUY : {:<10}'.format(price) + now() + '\n' over_write_file(directory=self.log, line_=line_) self.buy(price=price, amount=result.remaining_amount, order_type=order_type) elif result.side == 'sell': line_ = 'RETRY SELL : {:<10}'.format(price) + now() + '\n' over_write_file(directory=self.log, line_=line_) self.sell(price=price, amount=result.remaining_amount, order_type=order_type) elif operation == int(self.STAY): pass else: raise SchedulerCancelException('operation fail') def check_request(self): if self.is_waiting: price = float(self.api_gateway.use_ticker(pair=self.pair)['last']) # 売り if self.has_coin: if self.waiting_price <= price: self.waiting_price = None self.is_waiting = False self.contract_order_message() # 買い else: if self.waiting_price >= price: self.waiting_price = None self.is_waiting = False self.contract_order_message() def buy(self, price, amount, order_type): self.new_orders(price=price, amount=amount, side='buy', order_type=order_type) self.buying_price = price self.has_coin = True def sell(self, price, amount, order_type): self.new_orders(price=price, amount=amount, side='sell', order_type=order_type) self.buying_price = None self.has_coin = False def new_orders(self, price, amount, side, order_type, retry=0): """ 新規注文を行う :param price: number :param amount: number :param side: string :param order_type: string :param retry: integer """ try: # Orderインスタンス化 order = Order(order_id=0, pair=self.pair, side=side, type=order_type, price=price, start_amount=amount, remaining_amount=0, executed_amount=0, average_price=0, ordered_at=now(), status='') self.new_order_message(order=order, retry=retry) self.order_id += 1 self.waiting_price = price self.is_waiting = True print() print(order.ordered_at + ' ' + side + ' ' + order.start_amount + ' ' + str(order.price)) except Exception as e: print(e) self.error_message(message=e.args[0]) raise SchedulerCancelException('Fail to order') def cancel_orders(self, order_id): """ 現在の注文をキャンセルする :param order_id: number """ try: # 強制的にsideを決める result = { 'order_id': order_id, 'side': self.__side(), 'status': 'hoge', 'pair': 'hoge', 'price': 'hoge', 'average_price': 'hoge', 'start_amount': 'hoge', 'executed_amount': 'hoge', 'remaining_amount': 'hoge', 'ordered_at': 'hoge', 'type': 'hoge' } self.cancel_order_message(result=result) self.order_id -= 1 self.waiting_price = None self.is_waiting = False order = Order.order(r=result) return order except Exception as e: print(e) raise SchedulerCancelException('Fail to cancel order') def __side(self): if self.has_coin: return 'sell' elif self.has_coin: return 'buy'
class ZigZagAdviser: BUY = 1 STAY = 2 SELL = 3 TOP = 10 # 値幅率を超えて上がっているときの状態 BOTTOM = 11 # 値幅率を超えて下がっているときの状態 OTHER = 12 TOP_DECISION_TERM = 60 # BOTTOM_DECISION_TERM = 400 # FETCH_TERM = 4 # 4 /min CANDLESTICK = 15 # 15min def __init__(self, pair='xrp_jpy', candle_type='15min', buying_price=None, limit=None, init_max_high=None, init_min_low=None): self.__pair = pair self.__candle_type = candle_type self.__api_gateway = ApiGateway() self.rsi_data = None self.rsi_step = None self.max_high = None self.min_low = None self.price = None self.trend = None # 設定 self.buy_deviation = 0.03 self.sell_deviation = 0.02 self.rsi_term = 14 self.rsi_bottom = 40.0 self.rsi_top = 60.0 self.__line = Line() self.buying_price = buying_price self.limit = limit self.decision_term = 0 self.candlestick = self.make_price_data_frame() self.init_max_high = init_max_high self.init_min_low = init_min_low self() def __call__(self): self.is_candlestick = True self.zigzag_candlestick() self.is_candlestick = False self.candlestick = None # 初期値 if self.init_max_high is not None: self.max_high = self.init_max_high if self.init_min_low is not None: self.min_low = self.init_min_low def operation(self, has_coin): # 売りのエントリー if self.trend == self.TOP and has_coin: operation = self.SELL return operation, self.price # 買いのエントリー elif self.trend == self.BOTTOM and not has_coin: operation = self.BUY self.buying_price = self.price return operation, self.price elif self.trend == self.OTHER: operation = self.STAY return operation, self.price else: operation = self.STAY return operation, self.price def fetch_recent_data(self, price=None): """ 現在のtickerのapiを叩いて、最新の取引値を追加してデータを更新する """ if price is None: price = self.__api_gateway.use_ticker(pair=self.__pair) price = float(price['last']) self.__update_min_max(high=price, low=price) self.price = price # RSI self.__fetch_rsi() self.__trend() def __fetch_rsi(self): self.rsi_step += 1 # 新たな区間を追加 if self.rsi_step == self.FETCH_TERM * self.CANDLESTICK: self.rsi_step = 0 del self.rsi_data[0] self.rsi_data.append({ 'start': self.price, 'end': self.price, }) # 最後の区間を更新 else: self.rsi_data[-1]['end'] = self.price def zigzag_candlestick(self): self.max_high = float(self.candlestick.loc[0].high) self.min_low = float(self.candlestick.loc[0].low) for data_i in range(1, len(self.candlestick)): high = float(self.candlestick.loc[data_i].high) low = float(self.candlestick.loc[data_i].low) self.__update_min_max(high=high, low=low) self.__trend(high=high, low=low) # RSI self.rsi_data = list() for data_i in range(len(self.candlestick) - self.rsi_term, len(self.candlestick)): self.rsi_data.append({ 'start': float(self.candlestick.loc[data_i].open), 'end': float(self.candlestick.loc[data_i].end) }) self.rsi_step = 0 def rsi(self): plus = list() minus = list() for data in self.rsi_data: diff = data['end'] - data['start'] if diff > 0: plus.append(diff) else: minus.append(-1 * diff) if len(plus) > 0: plus_sum = sum(plus) else: plus_sum = 0 if len(minus) > 0: minus_sum = sum(minus) else: minus_sum = 0 return plus_sum / (plus_sum + minus_sum) * 100 def __update_min_max(self, high, low): if self.max_high < high: self.max_high = high if self.min_low > low: self.min_low = low def __top(self): """ 値幅率を超えて上がったときにTrue :return: """ if self.price is None: price = self.max_high else: price = self.price if self.buying_price is None or self.is_candlestick: return self.__and_gate( self.min_low * (1 + self.sell_deviation) < price, ) else: return self.__and_gate( self.min_low * (1 + self.sell_deviation) < price, self.buying_price <= self.price ) def __bottom(self): """ 値幅率を超えて下がったときにTrue :return: """ if self.price is None: price = self.min_low else: price = self.price if self.limit is None or self.is_candlestick: return self.__and_gate( self.max_high * (1 - self.buy_deviation) > price, ) else: return self.__and_gate( self.max_high * (1 - self.buy_deviation) > price, self.limit >= self.price ) def __trend(self, high=None, low=None): if high is None: high = self.price if low is None: low = self.price self.trend = self.OTHER if not self.is_candlestick: print(self.min_low, self.price, self.max_high) if self.__top(): # 最大値更新 if high >= self.max_high: self.decision_term = 0 if not self.is_candlestick: self.__line(message="最大値を更新") else: self.decision_term += 1 if not self.is_candlestick: rsi = self.rsi() self.__deliberating_message(side='sell', rsi=rsi) else: rsi = True # 山を決定 if self.is_candlestick or (self.decision_term >= self.TOP_DECISION_TERM and self.rsi_top <= rsi): self.decision_term = 0 self.trend = self.TOP self.min_low = low print('TOP') elif self.__bottom(): # 最小値更新 if low <= self.min_low: self.decision_term = 0 if not self.is_candlestick: self.__line(message="最小値を更新") else: self.decision_term += 1 # 谷を決定 if not self.is_candlestick: rsi = self.rsi() self.__deliberating_message(side='buy', rsi=rsi) else: rsi = True if self.is_candlestick or (self.decision_term >= self.BOTTOM_DECISION_TERM and self.rsi_bottom >= rsi): self.decision_term = 0 self.trend = self.BOTTOM self.max_high = high print('BOTTOM') else: self.decision_term = 0 def __deliberating_message(self, side, **kwargs): if side == 'buy': message = "買いエントリーを審議中\n" \ "decision : " + str(self.decision_term) + "\n" \ "RSI : " + str(kwargs['rsi']) + "\n" \ "" + str(now()) elif side == 'sell': message = "売りエントリーを審議中\n" \ "decision : " + str(self.decision_term) + "\n" \ "RSI : " + str(kwargs['rsi']) + "\n" \ "" + str(now()) else: message = "" if self.decision_term == 1 or self.decision_term % 10 == 0: self.__line(message=message) @staticmethod def __and_gate(*args): return all(args) def make_price_data_frame(self): """ 直近のロウソク足データ(2日分)から終値のデータフレームを作る :return: pandas.DataFrame 2日分のロウソク足データ """ today = datetime.datetime.now(timezone('UTC')) yesterday = today - datetime.timedelta(days=1) today = today.astimezone(timezone('Asia/Tokyo')) yesterday = yesterday.astimezone(timezone('Asia/Tokyo')) print('Initializing Candlestick Data From', today.strftime('%Y-%m-%d'), 'and', yesterday.strftime('%Y-%m-%d') ) candlestick_today = self.__api_gateway.use_candlestick( time=today.strftime("%Y%m%d"), candle_type=self.__candle_type, pair=self.__pair )['candlestick'][0]['ohlcv'] candlestick_yesterday = self.__api_gateway.use_candlestick( time=yesterday.strftime('%Y%m%d'), candle_type=self.__candle_type, pair=self.__pair )['candlestick'][0]['ohlcv'] for item in candlestick_today: candlestick_yesterday.append(item) return pd.DataFrame(candlestick_yesterday, columns=['open', 'high', 'low', 'end', 'yield', 'time'])
class MACDAdviser: MINUS = -1 PLUS = 1 BUY = 1 STAY = 2 SELL = 3 def __init__(self, short_term=12, long_term=26, signal=9, pair='xrp_jpy', candle_type='5min'): self.__short_term = short_term self.__long_term = long_term self.__signal = signal self.__pair = pair self.__candle_type = candle_type self.__api_gateway = ApiGateway() self.df_signal = None self.make_data_frame() self.trend_15min = None self.trend_5min = None self.area_15min = list() self.area_5min = list() self.max_histogram_5min = 0 self.max_histogram_15min = 0 self.start_macd_15min = None self.start_macd_5min = None self.start_signal_15min = None self.start_signal_5min = None self.mount_15min = None self.mount_5min = None self.count_15min = 1 self.count_5min = 1 self.is_plus_start_15min = None self.is_plus_start_5min = None self.max_price = None self.recognize() def operation(self, genome, has_coin): """ :return: const integer, float """ # price_rate = genome[28] price_rate = 0.9 histogram_15min = float(self.df_signal.tail(1).histogram_15min) histogram_5min = float(self.df_signal.tail(1).histogram_5min) histogram_1min = float(self.df_signal.tail(1).histogram_1min) pre_trend_15min = self.trend_15min pre_trend_5min = self.trend_5min macd_15min = float(self.df_signal.tail(1).macd_15min) macd_5min = float(self.df_signal.tail(1).macd_5min) macd_1min = float(self.df_signal.tail(1).macd_1min) signal_15min = float(self.df_signal.tail(1).signal_15min) signal_5min = float(self.df_signal.tail(1).signal_5min) signal_1min = float(self.df_signal.tail(1).signal_1min) price = float(self.df_signal.tail(1).price) self.__check_trend(histogram_15min=histogram_15min, histogram_5min=histogram_1min) check_5min = self.__check_5min() if check_5min: if pre_trend_15min == self.trend_15min: self.area_15min.append(histogram_15min) if abs(self.max_histogram_15min) < abs(histogram_15min): self.max_histogram_15min = histogram_15min else: self.area_15min = list() self.area_15min.append(histogram_15min) self.max_histogram_15min = histogram_15min self.start_macd_15min = macd_15min self.start_signal_15min = signal_15min if has_coin is False and signal_15min > 0: self.is_plus_start_15min = True else: self.is_plus_start_15min = False if pre_trend_5min == self.trend_5min: self.area_5min.append(histogram_1min) if abs(self.max_histogram_5min) < abs(histogram_1min): self.max_histogram_5min = histogram_1min else: self.area_5min = list() self.area_5min.append(histogram_1min) self.max_histogram_5min = histogram_1min self.start_macd_5min = macd_1min self.start_signal_5min = signal_1min if has_coin is False and signal_1min > 0: self.is_plus_start_5min = True else: self.is_plus_start_5min = False else: if pre_trend_5min == self.trend_5min: self.area_5min[-1] = histogram_1min if abs(self.max_histogram_5min) < abs(histogram_1min): self.max_histogram_5min = histogram_1min else: self.area_5min = list() self.area_5min.append(histogram_1min) self.max_histogram_5min = histogram_1min self.start_macd_5min = macd_1min self.start_signal_5min = signal_1min if has_coin is False and signal_1min > 0: self.is_plus_start_5min = True else: self.is_plus_start_5min = False # 山が下がり始めたら if len(self.area_5min) > 1 and abs( self.area_5min[-1]) > abs(histogram_1min): step_size_5min = len(self.area_5min) start_decrease_5min = True else: step_size_5min = None start_decrease_5min = False if len(self.area_15min) > 1 and abs(self.area_15min[-1]) < abs( self.area_15min[-2]): step_size_15min = len(self.area_15min) start_decrease_15min = True else: step_size_15min = None start_decrease_15min = False if start_decrease_5min and start_decrease_15min: if not has_coin and self.is_plus_start_15min and self.is_plus_start_5min: decrease_rate_15min = genome[0] step_rate_15min = genome[1] decrease_rate_5min = genome[2] step_rate_5min = genome[3] start_macd_15min = genome[4] start_signal_15min = genome[5] start_macd_5min = genome[6] start_signal_5min = genome[7] end_macd_15min = genome[8] end_signal_15min = genome[9] end_macd_5min = genome[10] end_signal_5min = genome[11] # MAX条件 max_threshold_5min = step_rate_5min * step_size_5min * self.max_histogram_5min max_threshold_5min += start_macd_5min * self.start_macd_5min max_threshold_5min += start_signal_5min * self.start_signal_5min max_threshold_5min += end_macd_5min * macd_5min max_threshold_5min += end_signal_5min * signal_5min max_threshold_15min = step_rate_15min * step_size_5min * self.max_histogram_15min max_threshold_15min += start_macd_15min * self.start_macd_15min max_threshold_15min += start_signal_15min * self.start_signal_15min max_threshold_15min += end_macd_15min * macd_15min max_threshold_15min += end_signal_15min * signal_15min # 降下条件 decrease_threshold_5min = self.max_histogram_5min * decrease_rate_5min decrease_threshold_15min = self.max_histogram_15min * decrease_rate_15min buy = self.and_gate( self.max_histogram_15min < max_threshold_15min, decrease_threshold_15min < histogram_15min, self.max_histogram_5min < max_threshold_5min, decrease_threshold_5min < histogram_1min, ) if buy: operation = self.BUY else: operation = self.STAY elif has_coin: decrease_rate_15min = genome[12] step_rate_15min = genome[13] decrease_rate_5min = genome[14] step_rate_5min = genome[15] start_macd_5min = genome[16] start_signal_5min = genome[17] start_macd_15min = genome[18] start_signal_15min = genome[19] end_macd_5min = genome[16] end_signal_5min = genome[17] end_macd_15min = genome[18] end_signal_15min = genome[19] # MAX条件 max_threshold_5min = step_rate_5min * step_size_5min * self.max_histogram_5min max_threshold_5min += start_macd_5min * self.start_macd_5min max_threshold_5min += start_signal_5min * self.start_signal_5min max_threshold_5min += end_macd_5min * macd_5min max_threshold_5min += end_signal_5min * signal_5min max_threshold_15min = step_rate_15min * step_size_15min * self.max_histogram_15min max_threshold_15min += start_macd_15min * self.start_macd_15min max_threshold_15min += start_signal_15min * self.start_signal_15min max_threshold_15min += end_macd_15min * macd_15min max_threshold_15min += end_signal_15min * signal_15min # 降下条件 decrease_threshold_5min = self.max_histogram_5min * decrease_rate_5min decrease_threshold_15min = self.max_histogram_15min * decrease_rate_15min if not self.max_price: self.max_price = price else: if self.max_price < price: self.max_price = price sell = self.and_gate( max_threshold_15min < self.max_histogram_15min, histogram_15min < decrease_threshold_15min, max_threshold_5min < self.max_histogram_5min, histogram_1min < decrease_threshold_5min, ) if self.max_price * price_rate > price: sell_price = True else: sell_price = False if sell or sell_price: operation = self.SELL self.max_price = None else: operation = self.STAY else: operation = self.STAY else: operation = self.STAY return operation, float(self.df_signal.tail(1).price) def fetch_recent_data(self): """ 現在のtickerのapiを叩いて、最新の取引値を追加してデータを更新する """ ticker = self.__api_gateway.use_ticker(pair=self.__pair) ticker = float(ticker['last']) tail = self.df_signal.tail(1) if self.count_15min == 15: self.count_15min = 1 short_15min = self.__exponential_moving_average( ticker, float(tail.short_15min), self.__short_term) long_15min = self.__exponential_moving_average( ticker, float(tail.long_15min), self.__long_term) macd_15min = short_15min - long_15min signal_15min = self.__exponential_moving_average( macd_15min, float(tail.signal_15min), self.__signal) histogram_15min = macd_15min - signal_15min else: self.count_15min += 1 short_15min = float(tail.short_15min) long_15min = float(tail.long_15min) macd_15min = float(tail.macd_15min) signal_15min = float(tail.signal_15min) histogram_15min = float(tail.histogram_15min) check_5min = self.__check_5min() if check_5min: short_5min = self.__exponential_moving_average( ticker, float(tail.short_5min), self.__short_term) long_5min = self.__exponential_moving_average( ticker, float(tail.long_5min), self.__long_term) macd_5min = short_5min - long_5min signal_5min = self.__exponential_moving_average( macd_5min, float(tail.signal_5min), self.__signal) histogram_5min = macd_5min - signal_5min else: short_5min = float(tail.short_5min) long_5min = float(tail.long_5min) macd_5min = float(tail.macd_5min) signal_5min = float(tail.signal_5min) histogram_5min = float(tail.histogram_5min) short_1min = self.__exponential_moving_average(ticker, short_5min, self.__short_term) long_1min = self.__exponential_moving_average(ticker, long_5min, self.__long_term) macd_1min = short_1min - long_1min signal_1min = self.__exponential_moving_average( macd_1min, signal_5min, self.__signal) histogram_1min = macd_1min - signal_1min add = pd.Series([ ticker, short_15min, long_15min, short_5min, long_5min, short_1min, long_1min, macd_15min, macd_5min, macd_1min, signal_15min, signal_5min, signal_1min, histogram_15min, histogram_5min, histogram_1min ], index=[ 'price', 'short_15min', 'long_15min', 'short_5min', 'long_5min', 'short_1min', 'long_1min', 'macd_15min', 'macd_5min', 'macd_1min', 'signal_15min', 'signal_5min', 'signal_1min', 'histogram_15min', 'histogram_5min', 'histogram_1min' ], name=len(self.df_signal) - 1) self.df_signal = self.df_signal.append(add) self.df_signal = self.df_signal.loc[1:] def recognize(self): """ 最近の状況を認識する """ size = len(self.df_signal) part = self.df_signal.loc[size - 1] self.__check_trend(histogram_15min=float(part.histogram_15min), histogram_5min=float(part.histogram_5min)) check_macd_15min = False pre_macd_15min = float(part.macd_15min) iteration = 2 change_15min = False change_5min = False while True: part = self.df_signal.loc[size - iteration] histogram_15min = float(part.histogram_15min) histogram_5min = float(part.histogram_5min) macd_15min = float(part.macd_15min) macd_5min = float(part.macd_5min) signal_15min = float(part.signal_15min) signal_5min = float(part.signal_5min) if pre_macd_15min == macd_15min and check_macd_15min: self.count_15min += 1 else: check_macd_15min = True pre_trend_15min = self.trend_15min pre_trend_5min = self.trend_5min self.__check_trend(histogram_15min=histogram_15min, histogram_5min=histogram_5min) # 山の終わり if pre_trend_15min != self.trend_15min and not change_15min: change_15min = True self.start_macd_15min = macd_15min self.start_signal_15min = signal_15min # 山の終わり if pre_trend_5min != self.trend_5min and not change_5min: change_5min = True self.start_macd_5min = macd_5min self.start_signal_5min = signal_5min if not change_15min: self.area_15min.append(histogram_15min) if abs(self.max_histogram_15min) < abs(histogram_15min): self.max_histogram_15min = histogram_15min if not change_5min: self.area_5min.append(histogram_5min) if abs(self.max_histogram_5min) < abs(histogram_5min): self.max_histogram_5min = histogram_5min if change_5min and change_15min: break iteration += 1 self.df_signal = self.df_signal.tail(10).reset_index(drop=True) def __check_trend(self, histogram_15min, histogram_5min): if histogram_15min >= 0: self.trend_15min = self.PLUS elif histogram_15min < 0: self.trend_15min = self.MINUS if histogram_5min >= 0: self.trend_5min = self.PLUS elif histogram_5min < 0: self.trend_5min = self.MINUS def __check_5min(self): if self.count_5min == 5: self.count_5min = 1 return True else: self.count_5min += 1 return False def make_data_frame(self): """ データを作成する """ df_price = self.make_price_data_frame() df_15min, df_5min = self.normalize_data_frame(df=df_price) df_macd, df_15min, df_5min = self.first_sma_data_frame( df_15min, df_5min) df_macd = self.make_macd_data_frame(df_macd, df_5min) self.df_signal = self.make_signal_data_frame(df_macd) def make_signal_data_frame(self, df_macd): part = df_macd.loc[:self.__signal * 3 - 1] sma_15min = float( np.sum(np.unique(part.macd_15min.values)) / self.__signal) sma_5min = float( np.sum(part.loc[self.__signal * 2:].macd_5min.values) / self.__signal) df_macd = df_macd.loc[self.__signal * 3:].reset_index(drop=True) df_signal = pd.DataFrame([[ part.tail(1).price, part.tail(1).short_15min, part.tail(1).long_15min, part.tail(1).short_5min, part.tail(1).long_5min, part.tail(1).short_5min, part.tail(1).long_5min, part.tail(1).macd_15min, part.tail(1).macd_5min, part.tail(1).macd_5min, sma_15min, sma_5min, sma_5min, part.tail(1).macd_15min - sma_15min, part.tail(1).macd_5min - sma_5min, part.tail(1).macd_5min - sma_5min, ]], columns=[ 'price', 'short_15min', 'long_15min', 'short_5min', 'long_5min', 'short_1min', 'long_1min', 'macd_15min', 'macd_5min', 'macd_1min', 'signal_15min', 'signal_5min', 'signal_1min', 'histogram_15min', 'histogram_5min', 'histogram_1min', ]) signal_15min = sma_15min signal_5min = sma_5min for macd_i in range(len(df_macd) - 1): if macd_i % 3 == 0 and macd_i != 0: signal_15min = self.__exponential_moving_average( value=df_macd.loc[macd_i].macd_15min, pre_value=signal_15min, term=self.__signal) signal_5min = self.__exponential_moving_average( value=df_macd.loc[macd_i].macd_5min, pre_value=signal_5min, term=self.__signal) df_signal.loc[macd_i + 1] = [ df_macd.loc[macd_i].price, df_macd.loc[macd_i].short_15min, df_macd.loc[macd_i].long_15min, df_macd.loc[macd_i].short_5min, df_macd.loc[macd_i].long_5min, df_macd.loc[macd_i].short_5min, df_macd.loc[macd_i].long_5min, df_macd.loc[macd_i].macd_15min, df_macd.loc[macd_i].macd_5min, df_macd.loc[macd_i].macd_5min, signal_15min, signal_5min, signal_5min, df_macd.loc[macd_i].macd_15min - signal_15min, df_macd.loc[macd_i].macd_5min - signal_5min, df_macd.loc[macd_i].macd_5min - signal_5min, ] return df_signal.loc[1:].reset_index(drop=True) def make_macd_data_frame(self, df_macd, df_5min): ema_15min_short = df_macd.loc[0].short_15min ema_15min_long = df_macd.loc[0].long_15min ema_5min_short = df_macd.loc[0].short_5min ema_5min_long = df_macd.loc[0].long_5min for i_5min in range(len(df_5min) - 1): if i_5min % 3 == 0 and i_5min != 0: ema_15min_short = self.__exponential_moving_average( value=df_5min.loc[i_5min].price, pre_value=ema_15min_short, term=self.__short_term) ema_15min_long = self.__exponential_moving_average( value=df_5min.loc[i_5min].price, pre_value=ema_15min_long, term=self.__long_term) ema_5min_short = self.__exponential_moving_average( value=df_5min.loc[i_5min].price, pre_value=ema_5min_short, term=self.__short_term) ema_5min_long = self.__exponential_moving_average( value=df_5min.loc[i_5min].price, pre_value=ema_5min_long, term=self.__long_term) df_macd.loc[i_5min + 1] = [ df_5min.loc[i_5min + 1].price, ema_15min_short, ema_15min_long, ema_5min_short, ema_5min_long, ema_15min_short - ema_15min_long, ema_5min_short - ema_5min_long, ] return df_macd.loc[1:].reset_index(drop=True) def make_price_data_frame(self): """ 直近のロウソク足データ(2日分)から終値のデータフレームを作る :return: pandas.DataFrame 2日分のロウソク足データ """ today = datetime.datetime.now(timezone('UTC')) yesterday = today - datetime.timedelta(days=1) today = today.astimezone(timezone('Asia/Tokyo')) yesterday = yesterday.astimezone(timezone('Asia/Tokyo')) print('Initializing Candlestick Data From', today.strftime('%Y-%m-%d'), 'and', yesterday.strftime('%Y-%m-%d')) candlestick_today = self.__api_gateway.use_candlestick( time=today.strftime("%Y%m%d"), candle_type=self.__candle_type, pair=self.__pair)['candlestick'][0]['ohlcv'] candlestick_yesterday = self.__api_gateway.use_candlestick( time=yesterday.strftime('%Y%m%d'), candle_type=self.__candle_type, pair=self.__pair)['candlestick'][0]['ohlcv'] candlestick_yesterday.extend(candlestick_today) candlestick = candlestick_yesterday del candlestick_today del candlestick_yesterday # 終値のみを取り出す candlestick = np.asarray(candlestick, dtype=float) candlestick = candlestick[0:, 3] return pd.DataFrame(candlestick, columns=['price']) @staticmethod def normalize_data_frame(df): """ 終値のデータフレームを15min, 5min, に分けて正規化する :param df: pandas.DataFrame :return: pandas.DataFrame, pandas.DataFrame """ # 3の倍数に揃える(古いデータを削る) df = df.loc[len(df) % 3:] df_15min = df.loc[::3].reset_index(drop=True) return df_15min, df @staticmethod def __exponential_moving_average(value, pre_value, term): return pre_value + (2 / (term + 1)) * (value - pre_value) def first_sma_data_frame(self, df_15min, df_5min): """ :param df_15min: :param df_5min: :return: ['short_15min', 'long_15min', 'short_5min', 'long_5min''macd_15min', 'macd_5min'], price_15min, price_5min """ sma_15min_short = self.sma_15min_short(df_15min)[0] sma_15min_long = self.sma_15min_long(df_15min)[0] data_15min = self.cut_for_ema_15min(df_15min) sma_5min_short = self.sma_5min_short(df_5min)[0] sma_5min_long = self.sma_5min_long(df_5min)[0] data_5min = self.cut_for_ema_5min(df_5min) ema = pd.DataFrame([[ data_5min.loc[0].price, sma_15min_short, sma_15min_long, sma_5min_short, sma_5min_long, sma_15min_short - sma_15min_long, sma_5min_short - sma_5min_long, ]], columns=[ 'price', 'short_15min', 'long_15min', 'short_5min', 'long_5min', 'macd_15min', 'macd_5min', ]) return ema, data_15min, data_5min def sma_15min_short(self, data_15min): """ 15minの短期単純移動平均 :param data_15min: :return: SMA, テスト用DataFrame """ part = data_15min.loc[(self.__long_term - self.__short_term):self.__long_term - 1] price_sum = np.sum(part.price.values) sma = float(price_sum / self.__short_term) return sma, part def sma_15min_long(self, data_15min): """ 15minの長期単純移動平均 :param data_15min: :return: SMA, テスト用DataFrame """ part = data_15min.loc[0:self.__long_term - 1] price_sum = np.sum(part.price.values) sma = float(price_sum / self.__long_term) return sma, part def sma_5min_short(self, data_5min): """ 5minの短期単純移動平均 :param data_5min: :return: SMA, テスト用のDataFrame """ # 15 = 5 * 3 part = data_5min.loc[self.__long_term * 3 - self.__short_term:self.__long_term * 3 - 1] price_sum = np.sum(part.price.values) sma = float(price_sum / self.__short_term) return sma, part def sma_5min_long(self, data_5min): """ 5minの長期単純移動平均 :param data_5min: :return: SMA, テスト用のDataFrame """ # 15 = 5 * 3 part = data_5min.loc[self.__long_term * 3 - self.__long_term:self.__long_term * 3 - 1] price_sum = np.sum(part.price.values) sma = float(price_sum / self.__long_term) return sma, part def cut_for_ema_15min(self, data_15min): """ SMAで使った部分を切り捨てる :param data_15min: :return: """ return data_15min[self.__long_term:].reset_index(drop=True) def cut_for_ema_5min(self, df): """ :param df: :return: """ return df[self.__long_term * 3:].reset_index(drop=True) @staticmethod def and_gate(*args): return all(args)
class Auto: BUY = 1 STAY = 2 SELL = 3 RETRY = 4 DEFAULT_TYPE = 'market' TYPE_LIMIT = 'limit' TYPE_MARKET = 'market' def __init__(self, adviser, pair, api_key=None, api_secret=None): """ :param adviser: bitbank.adviser テクニカル分析結果から売却の指示をするクラスのインスタンス :param pair: string 通貨のペア :param api_key: :param api_secret: """ self.adviser = adviser self.pair = pair self.coin = pair.split('_')[0] self.yen = pair.split('_')[1] self.api_gateway = ApiGateway(api_key=api_key, api_secret=api_secret) self.buying_price = None self.order_ids = None self.__line = Line() self.__start_price = self.fetch_price() def fetch_price(self): """ 開始時の価格を返す :return: string """ ticker = self.api_gateway.use_ticker(pair=self.pair) return float(ticker['last']) @staticmethod def __side_to_japanese(side): if side == 'buy': japanese = '買い' else: japanese = '売り' return japanese @staticmethod def __status_to_japanese(status): if status == 'UNFILLED': japanese = '注文中' elif status == 'PARTIALLY_FILLED': japanese = '注文中(一部約定)' elif status == 'FULLY_FILLED': japanese = '約定済み' elif status == 'CANCELED_UNFILLED': japanese = '取消済' elif status == 'CANCELED_PARTIALLY_FILLED': japanese = '取消済(一部約定)' else: japanese = 'None' return japanese def loss_cut_message(self): message = "損切りを行いました。" self.__line(message=message) def error_message(self, message): message = "エラー発生!!\n" \ "===================\n" \ "" + message + "\n" \ "===================" self.__line(message=message) def market_selling_message(self): message = "指値売り注文をキャンセルしましたので、成行注文を行います。" self.__line(message=message) def cancel_order_message(self, result): side = self.__side_to_japanese(side=result['side']) status = self.__status_to_japanese(status=result['status']) message = "注文を取り消しました。\n" \ "===================\n" \ "" + result['pair'] + " " + side + "注文 " + status + "\n" \ "注文ID: {}\n" \ "時刻: {}\n" \ "価格: {}\n" \ "平均価格: {}\n" \ "数量: {}\n" \ "約定数量: {}\n" \ "===================".format( result['order_id'], now(), result['price'], result['average_price'], result['start_amount'], result['executed_amount'], ) message.replace('n', '%0D%0A') self.__line(message=message) def new_order_message(self, order, retry): side = self.__side_to_japanese(side=order.side) status = self.__status_to_japanese(status=order.status) message = "新規注文を行いました。\n" \ "===================\n" \ "" + order.pair + " " + side + "注文 " + status + "\n" \ "注文ID: {}\n" \ "時刻: {}\n" \ "価格: {}\n" \ "数量: {}\n" \ "再要求回数: {}\n" \ "===================".format( order.order_id, order.ordered_at, order.price, order.start_amount, retry ) message.replace('n', '%0D%0A') self.__line(message=message) def contract_order_message(self): message = "約定しました。\n" \ "===================\n" \ "時刻: {}\n" \ "===================".format(now) message.replace('n', '%0D%0A') self.__line(message=message) def __operation_to_side(self, operation): if operation == int(self.BUY): return 'buy' elif operation == int(self.SELL): return 'sell' else: raise SchedulerCancelException()
class TestApiGateway(unittest.TestCase): def setUp(self): print('api_key: ', end="") api_key = '' print('api_secret: ', end="") api_secret = '' self.api_gateway = ApiGateway(api_key=api_key, api_secret=api_secret) self.order_id = None def test_use_depth(self): result = self.api_gateway.use_depth(pair='xrp_jpy') self.assertNotEqual(None, result['asks']) self.assertNotEqual(None, result['bids']) def test_use_ticker(self): result = self.api_gateway.use_ticker(pair='xrp_jpy') self.assertNotEqual(None, result['sell']) self.assertNotEqual(None, result['buy']) self.assertNotEqual(None, result['high']) self.assertNotEqual(None, result['low']) self.assertNotEqual(None, result['last']) self.assertNotEqual(None, result['vol']) result = self.api_gateway.use_ticker(pair='xrp_jpy') self.assertNotEqual(None, result['sell']) self.assertNotEqual(None, result['buy']) self.assertNotEqual(None, result['high']) self.assertNotEqual(None, result['low']) self.assertNotEqual(None, result['last']) self.assertNotEqual(None, result['vol']) def test_use_candlestick(self): result = self.api_gateway.use_candlestick(pair='xrp_jpy', candle_type='5min', time='20181130') self.assertNotEqual(None, result['candlestick']) self.assertEqual('5min', result['candlestick'][0]['type']) self.assertEqual(12 * 24, len(result['candlestick'][0]['ohlcv'])) def test_order(self): # new_order print('price: ', end='') self.price = input() print('amount: ', end='') self.amount = input() print('side: ', end='') self.side = input() result = self.api_gateway.new_order(pair='xrp_jpy', price=self.price, amount=self.amount, side=self.side, order_type='limit') self.assertNotEqual(None, result['order_id']) self.assertEqual('xrp_jpy', result['pair']) self.assertEqual(self.side, result['side']) self.assertEqual('limit', result['type']) self.assertEqual(self.amount, int(result['start_amount'])) self.assertNotEqual(None, result['executed_amount']) self.assertEqual(self.price, result['price']) self.assertNotEqual(None, result['average_price']) self.assertNotEqual(None, result['ordered_at']) self.assertNotEqual(None, result['status']) self.order_id = result['order_id'] print(result) # cancel_order result = self.api_gateway.cancel_order(pair='xrp_jpy', order_id=self.order_id) self.assertEqual(self.order_id, result['order_id']) self.assertEqual('xrp_jpy', result['pair']) self.assertEqual(self.side, result['side']) self.assertEqual('limit', result['type']) self.assertEqual(self.amount, int(result['start_amount'])) self.assertNotEqual(None, result['executed_amount']) self.assertEqual(self.price, result['price']) self.assertNotEqual(None, result['average_price']) self.assertNotEqual(None, result['ordered_at']) self.assertNotEqual(None, result['status']) print(result) # order_info result = self.api_gateway.use_orders_info(pair='xrp_jpy', order_ids=[self.order_id]) self.assertEqual(self.order_id, result['orders'][0]['order_id']) self.assertEqual('xrp_jpy', result['orders'][0]['pair']) self.assertEqual(self.side, result['orders'][0]['side']) self.assertEqual('limit', result['orders'][0]['type']) self.assertEqual(self.amount, int(result['orders'][0]['start_amount'])) self.assertNotEqual(None, result['orders'][0]['executed_amount']) self.assertEqual(self.price, result['orders'][0]['price']) self.assertNotEqual(None, result['orders'][0]['average_price']) self.assertNotEqual(None, result['orders'][0]['ordered_at']) self.assertNotEqual(None, result['orders'][0]['status']) print(result)
class BollingerBandSMATiAdviser: """ BollingerBandSMATiの内容にしたがって売買の指示を出す """ UPPER = 0 UPPER_UPPER = 1 UPPER_MIDDLE = 2 MIDDLE_LOWER = 3 LOWER_LOWER = 4 LOWER = 5 POSITIVE_INCLINATION = 1.376 NEGATIVE_INCLINATION = -1.376 POSITIVE_MIDDLE_INCLINATION = 0.325 NEGATIVE_MIDDLE_INCLINATION = -0.325 HYPER_EXPANSION = 0 EXPANSION = 1 FLAT = 2 SQUEEZE = 3 HYPER_SQUEEZE = 4 def __init__(self, stock_term, inclination_alpha, pair, candle_type='5min'): self.__recent_data = None self.__recent_sma = None self.__recent_sigma = None self.__volatility = None self.__last_location = None self.__pre_location = None self.__inclination_pattern = None self.__stock_term = stock_term self.__inclination_alpha = inclination_alpha self.__pair = pair self.__candle_type = candle_type self.__api_gateway = ApiGateway() self.__initialize() def __initialize(self): """ 直近のロウソク足データの終値でで初期化する """ # 直近のロウソク足データを読み込む candlestick = self.__fetch_recent_candlestick() # 必要な分のロウソク足データのみを切り取る candlestick = self.slice_off_candlestick(candlestick=candlestick) # ロウソク足データの終値のみを取り出す data_list = list() for data_i in range(len(candlestick)): # 始値, 高値, 安値, 終値, 出来高, UnixTime data_list.append(candlestick[data_i][3]) # データを使って計算する # 直近の単純移動平均線を求める self.__recent_sma = simple_moving_average(data=np.asarray( a=data_list, dtype=np.float32), term=self.__stock_term) print(self.__recent_sma) # 標準偏差を求める(1値) self.__recent_sigma = standard_deviation(data=self.__recent_sma, term=self.__stock_term) print(self.__recent_sigma) # ボラティリティーを求める self.__volatility = volatility(sma=self.__recent_sma[-1], std=self.__recent_sigma[-1]) # 計算に使うデータはnumpyに変換 self.__recent_data = np.asarray(a=data_list, dtype=np.float32) # 終値の位置を求める self.__location() def fetch_recent_data(self): """ 現在のtickerのapiを叩いて、最新の取引値を追加してデータを更新する """ ticker = self.__api_gateway.use_ticker(pair=self.__pair) ticker = float(ticker['last']) # データを更新 self.__recent_data = np.append(self.__recent_data, ticker) self.__recent_data = np.delete(self.__recent_data, 0) # 直近の単純移動平均線を求める self.__recent_sma = simple_moving_average(data=np.asarray( a=self.__recent_data, dtype=np.float32), term=self.__stock_term) # 標準偏差を求める self.__recent_sigma = standard_deviation(data=self.__recent_sma, term=self.__stock_term) # ボラティリティーを求める self.__volatility = volatility(sma=self.__recent_sma[-1], std=self.__recent_sigma[-1]) # 終値の位置を求める self.__pre_location = self.__last_location self.__location() def __inclination(self): """ 単純移動平均の1次線形回帰 :return: 傾きのパターン """ recent_sma = self.__recent_sma[len(self.__recent_sma) - self.__stock_term:len(self.__recent_sma )] print(len(self.__stock_term), len(recent_sma)) min_sma = np.amin(recent_sma) # 最小値との差分だけの行列を作る t = recent_sma - np.full_like(a=recent_sma, fill_value=min_sma) t = t * 1000 x = np.arange(start=0, step=self.__inclination_alpha, stop=self.__inclination_alpha * len(t)) # 直線(1次多項式)の線形回帰 # その傾きを取り出す inclination = linear_regression(x=x, t=t, basic_function=Polynomial(dim=2))[1] print('inclination: ' + str(inclination)) if self.POSITIVE_INCLINATION < inclination: inclination_pattern = self.HYPER_EXPANSION elif (self.POSITIVE_MIDDLE_INCLINATION < inclination) and (inclination <= self.POSITIVE_INCLINATION): inclination_pattern = self.EXPANSION elif (self.NEGATIVE_MIDDLE_INCLINATION <= inclination) and ( inclination <= self.POSITIVE_MIDDLE_INCLINATION): inclination_pattern = self.FLAT elif (self.NEGATIVE_INCLINATION <= inclination) and ( inclination < self.NEGATIVE_MIDDLE_INCLINATION): inclination_pattern = self.SQUEEZE elif inclination < self.NEGATIVE_INCLINATION: inclination_pattern = self.HYPER_SQUEEZE else: raise TypeError('inclination is None') return inclination_pattern def slice_off_candlestick(self, candlestick): """ 与えられたロウソク足データの必要な部分だけを切り取って返す関数 :param candlestick: list ロウソク足データ :return: list """ # 単純移動平均線 + 標準偏差 で(期間 - 1) * 1 を余分に使う data_size = self.__stock_term * 2 - 1 candlestick_size = len(candlestick) if candlestick_size < data_size: raise TypeError('candlestick not have much length', candlestick_size, data_size) # [start:stop:steps] stopは含まれない return candlestick[candlestick_size - data_size:candlestick_size] def __fetch_recent_candlestick(self): """ 直近のロウソク足データを2日分読み込む :return: list 2日分のロウソク足データ """ today = datetime.datetime.now(timezone('UTC')) yesterday = today - datetime.timedelta(days=1) today = today.astimezone(timezone('Asia/Tokyo')) yesterday = yesterday.astimezone(timezone('Asia/Tokyo')) print('Initializing Candlestick Data From', today.strftime('%Y-%m-%d'), 'and', yesterday.strftime('%Y-%m-%d')) candlestick_today = self.__api_gateway.use_candlestick( time=today.strftime("%Y%m%d"), candle_type=self.__candle_type, pair=self.__pair)['candlestick'][0]['ohlcv'] candlestick_yesterday = self.__api_gateway.use_candlestick( time=yesterday.strftime('%Y%m%d'), candle_type=self.__candle_type, pair=self.__pair)['candlestick'][0]['ohlcv'] candlestick_yesterday.extend(candlestick_today) candlestick = candlestick_yesterday del candlestick_today del candlestick_yesterday return candlestick def __location(self): """ 価格の位置を求める """ end_price = self.__recent_data[-1] if self.__volatility['double_upper'] < end_price: self.__last_location = self.UPPER elif (self.__volatility['upper'] < end_price) and (end_price <= self.__volatility['double_upper']): self.__last_location = self.UPPER_UPPER elif (self.__volatility['sma'] < end_price) and (end_price <= self.__volatility['upper']): self.__last_location = self.UPPER_MIDDLE elif (self.__volatility['lower'] <= end_price) and (end_price <= self.__volatility['sma']): self.__last_location = self.MIDDLE_LOWER elif (self.__volatility['double_lower'] <= end_price) and (end_price < self.__volatility['lower']): self.__last_location = self.LOWER_LOWER elif end_price < self.__volatility['double_lower']: self.__last_location = self.LOWER else: raise TypeError() def operation(self, genome, has_coin): """ データを更新して、複数個のシグマと前回、現在の終値の位置から取引の方針を決める :param genome: :param has_coin: :return: const int 取引方針をあらわす定数, float 最新の価格 """ self.__inclination_pattern = self.__inclination() action = self.determine_action(genome=genome, has_coin=has_coin) return action, self.__recent_data[-1] def determine_action(self, genome, has_coin): """ 終値、上部バンド、下部バンドから(買い,売り,保持)を決める ※ 遺伝子の特徴 [(前回の終値位置0~5 * 1)(現在の終値位置0~5 * 6)(傾きのパターン0~4 * 36)(ビットコインを持っているか0~1 * 180)] """ if has_coin: has_coin = 1 else: has_coin = 0 return genome[self.__pre_location * 1 + self.__last_location * 6 + self.__inclination_pattern * 36 + has_coin * 180] def get_recent_data(self): """ テスト用のゲッター :return: numpy """ return self.__recent_data