def __init__(self, exchange, symbol, leverage=None, api_key=None, api_secret=None, testnet=True, dry_run=False, candle_limit=None, candle_period=None): """ :param exchange: 거래소이름. bitmex, bithumb.. :param symbol: 심볼페어. XBTUSD, BTC/USD :param dry_run: 참일 경우 실제 주문 api를 호출하지 않는다. :param candle_limit: 저장할 최대 캔들갯수. :param candle_period: 봉주기. Bitmex는 4가지만 지원한다. 1m, 5m, 1h, 1d """ self.candle_handler = None raw_symbol = symbol.replace('/', '') self.api = utils.ccxt_exchange(exchange, api_key=api_key, api_secret=api_secret, is_async=False, opt={'test':testnet}) if api_key and api_secret and self.api and leverage is not None: self.api.private_post_position_leverage({'symbol': raw_symbol, 'leverage': leverage}) logger.info('>>candle_period>> %s',candle_period) # 웹소켓 처리기. self.ws = BitmexWS(raw_symbol, candle_period, api_key=api_key, api_secret=api_secret, testnet=testnet) if candle_limit and candle_period: period_in_second = 0 if candle_period == '1m': period_in_second = 60 elif candle_period == '5m': period_in_second = 300 elif candle_period == '1h': period_in_second = 3600 elif candle_period == '1d': period_in_second = 3600 * 24 since = datetime.datetime.now().timestamp() - period_in_second * candle_limit since = since * 1000 self.candle_handler = CandleHandler(self.api, symbol, period=candle_period, history=candle_limit, since=since)
def test_bitmex_data_ingest(self): exchange = utils.ccxt_exchange('bitmex', is_async=True) markets = asyncio.get_event_loop().run_until_complete( exchange.load_markets()) #exchange, symbols, start_date, end_date, periods base_dir, filepath = asyncio.get_event_loop().run_until_complete( data_ingest.ingest_data(exchange, 'XBT/USD', datetime(2019, 1, 1, 0, 0, 0), datetime(2019, 1, 1, 12, 0, 0), '5m', 12)) logger.debug('filepath > %s', filepath)
def __init__(self, exchange, symbol, leverage, candle_limit, candle_period, test_start, test_end): self.candle_handler = None self.symbol = symbol self.leverage = leverage self.api = utils.ccxt_exchange(exchange, is_async=True) self.candle_limit = candle_limit self.candle_period = candle_period self.test_start = test_start self.test_end = test_end
def test_ohlcv(self): api = utils.ccxt_exchange('bitmex', is_async=True) async def go(symbol, timeframe, limit): m = await api.load_markets() new_data = await api.fetch_ohlcv(symbol=symbol, timeframe=timeframe, limit=limit) print(new_data) await api.close() utils.test_async(go('XBT/USD', '1m', 10))
if test_start: test_start = datetime.strptime(test_start, '%Y-%m-%d %H:%M:%S%z') if test_end: test_end = datetime.strptime(test_end, '%Y-%m-%d %H:%M:%S%z') leverage = 1 candle_limit = 20 api_key = os.getenv('API_KEY') api_secret = os.getenv('API_SECRET') telegram_bot_token = os.getenv('TELEGRAM_BOT_TOKEN') telegram_chat_id = os.getenv('TELEGRAM_CHAT_ID') testnet = os.getenv('TESTNET') == 'True' dry_run = os.getenv('DRY_RUN') == 'True' api = utils.ccxt_exchange(exchange, api_key=api_key, api_secret=api_secret, is_async=False, testnet=testnet) api.private_post_position_leverage({ 'symbol': symbol, 'leverage': leverage }) ws = BitmexWS(symbol, candle_period, api_key=api_key, api_secret=api_secret, testnet=testnet) bot = Bot(api, ws, symbol=symbol,
def test_zigzag(self): api = utils.ccxt_exchange('bitmex', is_async=True) asyncio.get_event_loop().run_until_complete(api.load_markets()) _, filepath = asyncio.get_event_loop().run_until_complete( ingest_data(api, symbol='XBT/USD', start_date=datetime(2019, 1, 24, 5, 0, 0, tzinfo=timezone( timedelta(hours=9))), end_date=datetime(2019, 1, 26, 19, 59, 59, tzinfo=timezone(timedelta(hours=9))), interval='5m', history=0, reload=False)) print('filepath > ', filepath) data = pd.read_csv( filepath, index_col='Index', parse_dates=True, date_parser=lambda x: datetime.fromtimestamp(int(x) / 1000), usecols=['Index', 'Open', 'High', 'Low', 'Close', 'Volume']) # 조작시작. # data = data[300:500] plt.plot(data.Close) # z = zigzag(data, deviation=0.05) # plt.plot(z, 'ro') zz_high, zz_low = zigzag2(data, deviation=0.03, spread=1) plt.plot(zz_high, 'go') plt.plot(zz_low, 'ro') # 알고리즘. # 1. 저점이 올라가면 상승추세. 이전 고점 경신하면 # 2. 고점이 내려오면 하락추세. 이전 저점 깨지면.. # prev_high = None # my_index = [] # for i, v in zz_high.items(): # # print(i, v, prev_high) # if prev_high is not None: # if v < prev_high: # my_index.append((i, 'D')) # prev_high = v # # prev_low = None # for i, v in zz_low.items(): # # print(i, v, prev_low) # if prev_low is not None: # if v > prev_low: # my_index.append((i, 'U')) # prev_low = v # # my_index.sort() # # prev_ts = None # prev_type = None # for tup in my_index: # print(tup) # ts = tup[0] # type = tup[1] # # if prev_ts is None and prev_type is None: # prev_ts = ts # prev_type = type # else: # if type != prev_type: # plt.axvspan(prev_ts, ts, facecolor='g' if prev_type == 'U' else 'r', alpha=0.5) # prev_ts = ts # prev_type = type # print(my_index) ax = plt.gca() xfmt = md.DateFormatter('%Y-%m-%d %H:%M:%S') ax.xaxis.set_major_formatter(xfmt) plt.xticks(rotation=30) plt.subplots_adjust(bottom=0.2) plt.grid(True) fig = plt.gcf() fig.set_size_inches(16, 5) plt.show()
def test_heikin(self): api = utils.ccxt_exchange('bitmex', is_async=True) asyncio.get_event_loop().run_until_complete(api.load_markets()) _, filepath = asyncio.get_event_loop().run_until_complete( ingest_data(api, symbol='XBT/USD', start_date=datetime(2019, 1, 28, 12, 0, 0, tzinfo=timezone( timedelta(hours=9))), end_date=datetime(2019, 1, 29, 12, 0, 0, tzinfo=timezone(timedelta(hours=9))), interval='1m', history=0, reload=False)) print('filepath > ', filepath) data = pd.read_csv( filepath, index_col='Index', parse_dates=True, date_parser=lambda x: datetime.fromtimestamp(int(x) / 1000), usecols=['Index', 'Open', 'High', 'Low', 'Close', 'Volume']) ha = heikinashi(data) prev_diff = 0 pprev_diff = 0 trade = 0 entry_idx = None long_entry = None short_entry = None total_pnl = 0 r_index = [] r_value = [] N = 3 # 3개의 연속 가격을 확인하여 익절. for diff, ha_close, close, idx in zip(ha.HA_Diff, ha.HA_Close, data.Close, data.index): pnl = 0 # plt.axvspan(prev_ts, ts, facecolor='g' if prev_type == 'U' else 'r', alpha=0.5) # 갯수가 될때까지 기다린다. if short_entry is not None: # 숏 청산. if diff > 0 or self.great_or_eq( ha.HA_Close, N) or abs(short_entry - close) >= 1: pnl = short_entry - close total_pnl += pnl elapsed = idx - entry_idx r_index.append(idx) r_value.append(total_pnl) trade += 1 logger.info( '[%s] TOTAL_PNL[%s] PNL[$%s] SEC[%s] Price[%s->%s] Time[%s~%s]', trade, total_pnl, pnl, elapsed.seconds, short_entry, close, entry_idx, idx) short_entry = None elif long_entry is not None: if diff < 0 or self.less_or_eq( ha.HA_Close, N) or abs(long_entry - close) >= 1: pnl = close - long_entry total_pnl += pnl elapsed = idx - entry_idx r_index.append(idx) r_value.append(total_pnl) trade += 1 logger.info( '[%s] TOTAL_PNL[%s] PNL[$%s] SEC[%s] Price[%s->%s] Time[%s~%s]', trade, total_pnl, pnl, elapsed.seconds, long_entry, close, entry_idx, idx) long_entry = None # 청산하고 바로 다시 진입도 가능하다. if long_entry is None and short_entry is None: if diff > 0 and prev_diff > 0 and pprev_diff < 0: # 가격이 높아지는 추세. if prev_diff + diff >= 2: # 롱 진입. long_entry = close entry_idx = idx trade += 1 elif diff < 0 and prev_diff < 0 and pprev_diff > 0: # 가격이 낮아지는 추세. if prev_diff + diff <= -2: # 숏 진입. short_entry = close entry_idx = idx trade += 1 pprev_diff = prev_diff prev_diff = diff fig = plt.figure() ax1 = fig.add_subplot(2, 1, 1) ax2 = fig.add_subplot(2, 1, 2) # 차트1 ax1.plot(data.Close) # 차트2 pnl_series = pd.Series(data=r_value, index=r_index) ax2.plot(pnl_series, 'ro') ax = plt.gca() xfmt = md.DateFormatter('%Y-%m-%d %H:%M:%S') ax.xaxis.set_major_formatter(xfmt) plt.xticks(rotation=30) plt.subplots_adjust(bottom=0.2) plt.grid(True) fig = plt.gcf() fig.set_size_inches(16, 7) plt.show()