├── .github └── CODEOWNERS ├── setup.cfg ├── upbitpy ├── __init__.py └── upbitpy.py ├── .travis.yml ├── samples ├── README.md ├── get_min_candle.md ├── get_min_candle.py ├── get_all_price.py ├── get_volume_ratio.py ├── get_volume_ratio.md └── get_all_price.md ├── setup.py ├── README.md ├── LICENSE ├── .gitignore └── test ├── test.py └── test_exchange.py /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @inasie -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /upbitpy/__init__.py: -------------------------------------------------------------------------------- 1 | from upbitpy.upbitpy import Upbitpy 2 | 3 | __version__ = '1.0.0' -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6.7" 4 | install: 5 | - pip install --upgrade upbitpy 6 | script: 7 | - pytest test/test.py 8 | -------------------------------------------------------------------------------- /samples/README.md: -------------------------------------------------------------------------------- 1 | # Samples 2 | 3 | - [모든 코인 가격 가져오기](./get_all_price.md) 4 | - [일정 간격으로 분봉 가져오기](./get_min_candle.md) 5 | - [24시간 평균 거래량 대비 5분 거래량 비율](./get_volume_ratio.md) -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | setup( 4 | name='upbitpy', 5 | version='1.0.1', 6 | description='upbit open API python wrapper', 7 | url='https://github.com/inasie/upbitpy', 8 | author='inasie', 9 | author_email='inasie@naver.com', 10 | license='MIT', 11 | install_requires=[ 12 | 'requests==2.21.0', 13 | 'pyjwt==1.7.1', 14 | ], 15 | python_requires='>=3', 16 | packages=find_packages(), 17 | zip_safe=False 18 | ) 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Upbitpy 2 | 3 | [![Build Status](https://travis-ci.org/inasie/upbitpy.svg?branch=master)](https://travis-ci.org/inasie/upbitpy) 4 | 5 | [Upbit API](https://docs.upbit.com/v1.0/reference) for Python3 6 | 7 | ## Install 8 | ```bash 9 | $ pip3 install upbitpy 10 | ``` 11 | 12 | ## Usage 13 | ```python 14 | from upbitpy import Upbitpy 15 | 16 | upbit = Upbitpy() 17 | tickers = upbit.get_ticker(['KRW-BTC', 'KRW-EOS']) 18 | for ticker in tickers: 19 | print('%s trade price : %d' % (ticker['market'], ticker['trade_price'])) 20 | ``` 21 | 22 | ## Samples 23 | 24 | [samples/README.md](./samples/README.md) 25 | 26 | ## TC 27 | 28 | Please refer test/test.py 29 | -------------------------------------------------------------------------------- /samples/get_min_candle.md: -------------------------------------------------------------------------------- 1 | # 일정 간격으로 분봉 가져오기 2 | 3 | - get_min_candle.py 4 | 5 | ## 출력 6 | 7 | ```bash 8 | $ python samples/get_min_candle.py 9 | INFO:root:[20190902 05:48:24] KRW-BTC 10 | INFO:root: opening_price: 11636000.0 11 | INFO:root: trade_price: 11636000.0 12 | INFO:root: high_price: 11636000.0 13 | INFO:root: low_price: 11636000.0 14 | INFO:root: timestamp: 1567370931373 15 | INFO:root:[20190902 05:49:00] KRW-BTC 16 | INFO:root: opening_price: 11636000.0 17 | INFO:root: trade_price: 11636000.0 18 | INFO:root: high_price: 11637000.0 19 | INFO:root: low_price: 11636000.0 20 | INFO:root: timestamp: 1567370967198 21 | ``` 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 inasie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /samples/get_min_candle.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from upbitpy import Upbitpy 4 | import datetime 5 | import logging 6 | import time 7 | 8 | INTERVAL_MIN = 1 # 간격 (1,3,5,10,15,30,60,240) 9 | 10 | # System 시간 기준으로 Timer를 돌리기 위한 function 11 | # min=1 이라면, 7시 12분 35초에 function이 호출되었다면 25초 sleep 12 | # min=5 이라면, 7시 12분 35초에 function이 호출되었다면 2분 25초 sleep 13 | def wait(min): 14 | now = datetime.datetime.now() 15 | remain_second = 60 - now.second 16 | remain_second += 60 * (min - (now.minute % min + 1)) 17 | time.sleep(remain_second) 18 | 19 | 20 | def main(): 21 | upbit = Upbitpy() 22 | keys = ['opening_price', 'trade_price', 'high_price', 'low_price', 'timestamp'] 23 | 24 | while True: 25 | coin = 'KRW-BTC' 26 | candle = upbit.get_minutes_candles(INTERVAL_MIN, 'KRW-BTC')[0] 27 | logging.info('[{}] {}'.format(datetime.datetime.now().strftime('%Y%m%d %H:%M:%S'), coin)) 28 | for key in keys: 29 | logging.info('\t{}: {}'.format(key, candle[key])) 30 | wait(INTERVAL_MIN) 31 | 32 | 33 | if __name__ == '__main__': 34 | logging.basicConfig(level=logging.INFO) 35 | main() 36 | -------------------------------------------------------------------------------- /samples/get_all_price.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from upbitpy import Upbitpy 4 | import logging 5 | 6 | 7 | def print_tickers(items): 8 | for it in items: 9 | if it['market'].startswith('KRW'): 10 | logging.info('{}: {} 원'.format(it['market'], it['trade_price'])) 11 | elif it['market'].startswith('BTC'): 12 | logging.info('{}: {} btc'.format(it['market'], format(it['trade_price'], '.8f'))) 13 | elif it['market'].startswith('ETH'): 14 | logging.info('{}: {} eth'.format(it['market'], format(it['trade_price'], '.8f'))) 15 | elif it['market'].startswith('USDT'): 16 | logging.info('{}: {} usdt'.format(it['market'], format(it['trade_price'], '.3f'))) 17 | 18 | 19 | def main(): 20 | upbit = Upbitpy() 21 | 22 | # 모든 market 얻어오기 23 | all_market = upbit.get_market_all() 24 | 25 | # market 분류 26 | market_table = { 27 | 'BTC': [], 28 | 'KRW': [], 29 | 'ETH': [], 30 | 'USDT': [] 31 | } 32 | for m in all_market: 33 | for key in market_table.keys(): 34 | if m['market'].startswith(key): 35 | market_table[key].append(m['market']) 36 | 37 | # 마켓 별 가격을 가져와 출력 38 | for key in market_table.keys(): 39 | logging.info('{} 마켓:'.format(key)) 40 | tickers = upbit.get_ticker(market_table[key]) 41 | print_tickers(tickers) 42 | 43 | 44 | if __name__ == '__main__': 45 | logging.basicConfig(level=logging.INFO) 46 | main() 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /samples/get_volume_ratio.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from upbitpy import Upbitpy 4 | import datetime 5 | import logging 6 | import time 7 | 8 | INTERVAL_MIN = 5 # 간격 9 | 10 | def wait(min): 11 | now = datetime.datetime.now() 12 | remain_second = 60 - now.second 13 | remain_second += 60 * (min - (now.minute % min + 1)) 14 | time.sleep(remain_second) 15 | 16 | 17 | # candle 요청 회수 제한이 걸리면 1초 sleep 18 | def check_remaining_candles_req(upbit): 19 | ret = upbit.get_remaining_req() 20 | if ret is None: 21 | return 22 | if 'candles' not in ret.keys(): 23 | return 24 | if int(ret['candles']['sec']) == 0: 25 | logging.debug('>>> sleep 1 seconds') 26 | time.sleep(1) 27 | 28 | 29 | def main(): 30 | upbit = Upbitpy() 31 | 32 | # 모든 원화 market 얻어오기 33 | all_market = upbit.get_market_all() 34 | krw_markets = [] 35 | for m in all_market: 36 | if m['market'].startswith('KRW'): 37 | krw_markets.append(m['market']) 38 | 39 | candles_7d = dict() 40 | # 7일간 거래량 41 | for m in krw_markets: 42 | candles_7d[m] = upbit.get_weeks_candles(m, count=1)[0] 43 | check_remaining_candles_req(upbit) 44 | 45 | while True: 46 | logging.info('평균 거래량 대비 {}분 거래량 비율========================'.format(INTERVAL_MIN)) 47 | for m in krw_markets: 48 | vol = upbit.get_minutes_candles(1, m, count=1)[0]['candle_acc_trade_volume'] 49 | vol_7d = candles_7d[m]['candle_acc_trade_volume'] 50 | vol_7d_avg = (((vol_7d/7.0)/24.0)/60.0)*INTERVAL_MIN 51 | vol_ratio = format((vol/vol_7d_avg)*100.0, '.2f') 52 | logging.info('[{}] {}% (거래량:{}, 평균:{})'.format( 53 | m, vol_ratio, format(vol, '.2f'), format(vol_7d_avg, '.2f'))) 54 | check_remaining_candles_req(upbit) 55 | wait(INTERVAL_MIN) 56 | 57 | 58 | if __name__ == '__main__': 59 | logging.basicConfig(level=logging.INFO) 60 | main() 61 | -------------------------------------------------------------------------------- /test/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from upbitpy import Upbitpy 3 | import unittest 4 | import logging 5 | 6 | 7 | class UpbitpyTest(unittest.TestCase): 8 | 9 | def test_get_market_all(self): 10 | upbit = Upbitpy() 11 | ret = upbit.get_market_all() 12 | self.assertIsNotNone(ret) 13 | self.assertNotEqual(len(ret), 0) 14 | logging.info(ret) 15 | logging.info(upbit.get_remaining_req()) 16 | 17 | def test_get_minutes_candles(self): 18 | upbit = Upbitpy() 19 | ret = upbit.get_minutes_candles(60, 'KRW-BTC') 20 | self.assertIsNotNone(ret) 21 | self.assertNotEqual(len(ret), 0) 22 | logging.info(ret) 23 | logging.info(upbit.get_remaining_req()) 24 | 25 | def test_get_days_candles(self): 26 | upbit = Upbitpy() 27 | ret = upbit.get_days_candles('KRW-ADA') 28 | self.assertIsNotNone(ret) 29 | logging.info(ret) 30 | logging.info(upbit.get_remaining_req()) 31 | 32 | def test_get_weeks_candles(self): 33 | upbit = Upbitpy() 34 | ret = upbit.get_weeks_candles('KRW-ICX') 35 | self.assertIsNotNone(ret) 36 | self.assertNotEqual(len(ret), 0) 37 | logging.info(ret) 38 | logging.info(upbit.get_remaining_req()) 39 | 40 | def test_get_months_candles(self): 41 | upbit = Upbitpy() 42 | ret = upbit.get_months_candles('BTC-ETH') 43 | self.assertIsNotNone(ret) 44 | self.assertNotEqual(len(ret), 0) 45 | logging.info(ret) 46 | logging.info(upbit.get_remaining_req()) 47 | 48 | def test_get_trades_ticks(self): 49 | upbit = Upbitpy() 50 | ret = upbit.get_trades_ticks('KRW-ICX') 51 | self.assertIsNotNone(ret) 52 | self.assertNotEqual(len(ret), 0) 53 | logging.info(ret) 54 | logging.info(upbit.get_remaining_req()) 55 | 56 | def test_get_ticker(self): 57 | upbit = Upbitpy() 58 | ret = upbit.get_ticker(['KRW-ICX', 'KRW-ADA']) 59 | self.assertIsNotNone(ret) 60 | self.assertNotEqual(len(ret), 0) 61 | logging.info(ret) 62 | logging.info(upbit.get_remaining_req()) 63 | 64 | def test_get_orderbook(self): 65 | upbit = Upbitpy() 66 | ret = upbit.get_orderbook(['KRW-ICX', 'KRW-ADA']) 67 | self.assertIsNotNone(ret) 68 | self.assertNotEqual(len(ret), 0) 69 | logging.info(ret) 70 | logging.info(upbit.get_remaining_req()) 71 | 72 | 73 | if __name__ == '__main__': 74 | logging.basicConfig(level=logging.INFO) 75 | unittest.main() 76 | -------------------------------------------------------------------------------- /test/test_exchange.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from upbitpy import Upbitpy 4 | import unittest 5 | import logging 6 | 7 | class UpbitpyExchangeTest(unittest.TestCase): 8 | KEY = '' 9 | SECRET = '' 10 | 11 | TEST_MARKET = '' 12 | TEST_BID_PRICE = 0 13 | TEST_VOLUME = 0 14 | 15 | def test_get_get_accounts(self): 16 | upbit = Upbitpy(self.KEY, self.SECRET) 17 | ret = upbit.get_accounts() 18 | self.assertIsNotNone(ret) 19 | self.assertNotEqual(len(ret), 0) 20 | logging.info(ret) 21 | 22 | 23 | def test_get_chance(self): 24 | upbit = Upbitpy(self.KEY, self.SECRET) 25 | ret = upbit.get_chance(self.TEST_MARKET) 26 | self.assertIsNotNone(ret) 27 | self.assertNotEqual(len(ret), 0) 28 | logging.info(ret) 29 | 30 | 31 | def test_order(self): 32 | upbit = Upbitpy(self.KEY, self.SECRET) 33 | ret = upbit.order(self.TEST_MARKET, 'bid', self.TEST_VOLUME, self.TEST_BID_PRICE) 34 | self.assertIsNotNone(ret) 35 | self.assertNotEqual(len(ret), 0) 36 | logging.info(ret) 37 | self.__do_cancel(upbit) 38 | 39 | 40 | def test_get_orders(self): 41 | upbit = Upbitpy(self.KEY, self.SECRET) 42 | self.__do_temp_order(upbit) 43 | ret = upbit.get_orders(self.TEST_MARKET, 'wait') 44 | self.assertIsNotNone(ret) 45 | self.assertNotEqual(len(ret), 0) 46 | logging.info(ret) 47 | self.__do_cancel(upbit) 48 | 49 | 50 | def test_cancel_order(self): 51 | upbit = Upbitpy(self.KEY, self.SECRET) 52 | uuid = self.__do_temp_order(upbit) 53 | self.assertIsNotNone(uuid) 54 | ret = upbit.cancel_order(uuid) 55 | self.assertIsNotNone(ret) 56 | self.assertNotEqual(len(ret), 0) 57 | logging.info(ret) 58 | 59 | 60 | def __do_cancel(self, upbit): 61 | uuid = self.__get_temp_order(upbit) 62 | if uuid is not None: 63 | upbit.cancel_order(uuid) 64 | 65 | 66 | def __do_temp_order(self, upbit): 67 | upbit.order(self.TEST_MARKET, 'bid', self.TEST_VOLUME, self.TEST_BID_PRICE) 68 | ret = upbit.get_orders(self.TEST_MARKET, 'wait') 69 | if ret is None or len(ret) == 0: 70 | return None 71 | return ret[0]['uuid'] 72 | 73 | 74 | def __get_temp_order(self, upbit): 75 | ret = upbit.get_orders(self.TEST_MARKET, 'wait') 76 | if ret is None or len(ret) == 0: 77 | return None 78 | return ret[0]['uuid'] 79 | 80 | 81 | if __name__ == '__main__': 82 | logging.basicConfig(level=logging.INFO) 83 | 84 | # key/secret 생성 방법: 85 | # 업비트 로그인 -> 마이페이지 -> Open API 관리 -> Open API Key 관리 -> 권한 설정 후 Open API Key 발급받기 86 | UpbitpyExchangeTest.KEY = 'put your key' 87 | UpbitpyExchangeTest.SECRET = 'put your secret' 88 | 89 | # 기본 테스트 환경: xrp, 10원에 100개 구매 (구매 요청 후 취소) 90 | UpbitpyExchangeTest.TEST_MARKET = 'KRW-XRP' 91 | UpbitpyExchangeTest.TEST_BID_PRICE = 10 92 | UpbitpyExchangeTest.TEST_VOLUME = 100 93 | 94 | unittest.main() 95 | -------------------------------------------------------------------------------- /samples/get_volume_ratio.md: -------------------------------------------------------------------------------- 1 | # 7일 평균 거래량 대비 x분 거래량 비율 2 | 3 | - get_volume_ratio.py 4 | - INTERVAL_MIN 값으로 조정 5 | 6 | ## 출력 7 | 8 | ```bash 9 | $ python samples/get_volume_ratio.py 10 | python get_volume_ratio.py 11 | INFO:root:평균 거래량 대비 5분 거래량 비율======================== 12 | INFO:root:[KRW-BTC] 346.73% (거래량:8.64, 평균:2.49) 13 | INFO:root:[KRW-DASH] 855.35% (거래량:0.98, 평균:0.11) 14 | INFO:root:[KRW-ETH] 254.56% (거래량:66.96, 평균:26.30) 15 | INFO:root:[KRW-NEO] 1503.90% (거래량:49.81, 평균:3.31) 16 | INFO:root:[KRW-MTL] 271.95% (거래량:1925.36, 평균:707.98) 17 | INFO:root:[KRW-LTC] 1725.82% (거래량:83.01, 평균:4.81) 18 | INFO:root:[KRW-STRAT] 3114.94% (거래량:3772.03, 평균:121.09) 19 | INFO:root:[KRW-XRP] 289.79% (거래량:46409.92, 평균:16015.26) 20 | INFO:root:[KRW-ETC] 2.92% (거래량:2.64, 평균:90.43) 21 | INFO:root:[KRW-OMG] 1580.84% (거래량:483.52, 평균:30.59) 22 | INFO:root:[KRW-SNT] 96.49% (거래량:4475.73, 평균:4638.37) 23 | INFO:root:[KRW-WAVES] 30.65% (거래량:7.80, 평균:25.45) 24 | INFO:root:[KRW-PIVX] 28.07% (거래량:664.07, 평균:2365.36) 25 | INFO:root:[KRW-XEM] 5.54% (거래량:31.62, 평균:571.11) 26 | INFO:root:[KRW-ZEC] 49.58% (거래량:0.24, 평균:0.48) 27 | INFO:root:[KRW-XMR] 798.76% (거래량:1.79, 평균:0.22) 28 | INFO:root:[KRW-QTUM] 396.41% (거래량:650.83, 평균:164.18) 29 | INFO:root:[KRW-GNT] 133.84% (거래량:3962.70, 평균:2960.76) 30 | INFO:root:[KRW-LSK] 742.19% (거래량:30.83, 평균:4.15) 31 | INFO:root:[KRW-STEEM] 2839.37% (거래량:5000.00, 평균:176.10) 32 | INFO:root:[KRW-XLM] 123.55% (거래량:2358.00, 평균:1908.52) 33 | INFO:root:[KRW-ARDR] 90.69% (거래량:805.46, 평균:888.13) 34 | INFO:root:[KRW-KMD] 92.75% (거래량:50.00, 평균:53.91) 35 | INFO:root:[KRW-ARK] 172.78% (거래량:39.06, 평균:22.61) 36 | INFO:root:[KRW-STORJ] 20.93% (거래량:165.00, 평균:788.49) 37 | INFO:root:[KRW-GRS] 411.63% (거래량:3143.27, 평균:763.61) 38 | INFO:root:[KRW-VTC] 35.95% (거래량:3.52, 평균:9.79) 39 | INFO:root:[KRW-REP] 395.62% (거래량:4.37, 평균:1.11) 40 | INFO:root:[KRW-EMC2] 115.74% (거래량:2595.31, 평균:2242.45) 41 | INFO:root:[KRW-ADA] 51.28% (거래량:10000.00, 평균:19500.85) 42 | INFO:root:[KRW-SBD] 458.64% (거래량:26.72, 평균:5.83) 43 | INFO:root:[KRW-POWR] 3429.89% (거래량:30419.74, 평균:886.90) 44 | INFO:root:[KRW-BTG] 1056.80% (거래량:114.21, 평균:10.81) 45 | INFO:root:[KRW-ICX] 257.26% (거래량:2080.00, 평균:808.51) 46 | INFO:root:[KRW-EOS] 272.99% (거래량:1661.94, 평균:608.79) 47 | INFO:root:[KRW-STORM] 823.39% (거래량:58850.11, 평균:7147.30) 48 | INFO:root:[KRW-TRX] 25.05% (거래량:13963.58, 평균:55744.80) 49 | INFO:root:[KRW-MCO] 1467.73% (거래량:32.59, 평균:2.22) 50 | INFO:root:[KRW-SC] 1.09% (거래량:225.00, 평균:20615.36) 51 | INFO:root:[KRW-GTO] 80.72% (거래량:10000.00, 평균:12388.62) 52 | INFO:root:[KRW-IGNIS] 355.06% (거래량:95749.65, 평균:26967.01) 53 | INFO:root:[KRW-ONT] 155.83% (거래량:51.38, 평균:32.97) 54 | INFO:root:[KRW-DCR] 3199.31% (거래량:5.36, 평균:0.17) 55 | INFO:root:[KRW-ZIL] 71.87% (거래량:7657.48, 평균:10654.59) 56 | INFO:root:[KRW-POLY] 1428.52% (거래량:19469.59, 평균:1362.92) 57 | INFO:root:[KRW-ZRX] 0.85% (거래량:0.85, 평균:100.79) 58 | INFO:root:[KRW-SRN] 1783.89% (거래량:83093.79, 평균:4658.01) 59 | INFO:root:[KRW-LOOM] 81.47% (거래량:1583.58, 평균:1943.69) 60 | INFO:root:[KRW-BCH] 468.02% (거래량:23.00, 평균:4.92) 61 | INFO:root:[KRW-ADT] 181.69% (거래량:1612.93, 평균:887.72) 62 | INFO:root:[KRW-ADX] 13580.74% (거래량:13952.78, 평균:102.74) 63 | INFO:root:[KRW-BAT] 0.88% (거래량:2.28, 평균:257.84) 64 | INFO:root:[KRW-IOST] 564.13% (거래량:6133.00, 평균:1087.16) 65 | INFO:root:[KRW-DMT] 1584.52% (거래량:5000.00, 평균:315.55) 66 | INFO:root:[KRW-RFR] 538.66% (거래량:248760.77, 평균:46181.70) 67 | INFO:root:[KRW-CVC] 54.00% (거래량:756.00, 평균:1399.93) 68 | INFO:root:[KRW-IQ] 174.53% (거래량:18196.43, 평균:10425.78) 69 | INFO:root:[KRW-IOTA] 135.05% (거래량:103.00, 평균:76.27) 70 | INFO:root:[KRW-OST] 7558.86% (거래량:183401.28, 평균:2426.31) 71 | INFO:root:[KRW-MFT] 1019.67% (거래량:520478.98, 평균:51043.83) 72 | INFO:root:[KRW-ONG] 618.64% (거래량:998.00, 평균:161.32) 73 | INFO:root:[KRW-GAS] 349.55% (거래량:26.90, 평균:7.70) 74 | INFO:root:[KRW-MEDX] 12.98% (거래량:1119.87, 평균:8626.25) 75 | INFO:root:[KRW-UPP] 1047.55% (거래량:50038.22, 평균:4776.70) 76 | INFO:root:[KRW-ELF] 1563.44% (거래량:23693.64, 평균:1515.48) 77 | INFO:root:[KRW-KNC] 350.26% (거래량:395.96, 평균:113.05) 78 | INFO:root:[KRW-BSV] 7.39% (거래량:0.34, 평균:4.58) 79 | INFO:root:[KRW-THETA] 1959.33% (거래량:10491.04, 평균:535.44) 80 | INFO:root:[KRW-EDR] 116.39% (거래량:3809.63, 평균:3273.07) 81 | INFO:root:[KRW-QKC] 1.38% (거래량:200.00, 평균:14508.01) 82 | INFO:root:[KRW-CPT] 8.68% (거래량:1337.29, 평균:15405.81) 83 | INFO:root:[KRW-BTT] 247.87% (거래량:1000000.00, 평균:403430.05) 84 | INFO:root:[KRW-MOC] 36.01% (거래량:1421.00, 평균:3946.43) 85 | INFO:root:[KRW-COSM] 1568.55% (거래량:268609.80, 평균:17124.76) 86 | INFO:root:[KRW-ENJ] 254.96% (거래량:49153.51, 평균:19279.26) 87 | INFO:root:[KRW-TFUEL] 756.76% (거래량:102283.14, 평균:13515.84) 88 | INFO:root:[KRW-MANA] 1768.91% (거래량:3196.38, 평균:180.70) 89 | INFO:root:[KRW-ANKR] 15.02% (거래량:3118.81, 평균:20759.42) 90 | INFO:root:[KRW-NPXS] 13.27% (거래량:15000.00, 평균:113057.89) 91 | INFO:root:[KRW-TTC] 878.55% (거래량:51334.31, 평균:5843.05) 92 | INFO:root:[KRW-AERGO] 13.90% (거래량:47.15, 평균:339.24) 93 | INFO:root:[KRW-ATOM] 90.30% (거래량:75.72, 평균:83.86) 94 | INFO:root:[KRW-TT] 0.54% (거래량:100.00, 평균:18352.15) 95 | INFO:root:[KRW-CRE] 1.68% (거래량:1540.57, 평균:91771.97) 96 | INFO:root:[KRW-SOLVE] 34.76% (거래량:1674.77, 평균:4817.49) 97 | INFO:root:[KRW-MBL] 94.23% (거래량:39331.87, 평균:41741.52) 98 | INFO:root:[KRW-TSHP] 53.76% (거래량:10644.78, 평균:19799.87) 99 | INFO:root:[KRW-WAXP] 17.43% (거래량:192.56, 평균:1104.74) 100 | INFO:root:평균 거래량 대비 5분 거래량 비율======================== 101 | INFO:root:[KRW-BTC] 537.28% (거래량:13.38, 평균:2.49) 102 | INFO:root:[KRW-DASH] 855.35% (거래량:0.98, 평균:0.11) 103 | INFO:root:[KRW-ETH] 221.96% (거래량:58.38, 평균:26.30) 104 | INFO:root:[KRW-NEO] 116.56% (거래량:3.86, 평균:3.31) 105 | INFO:root:[KRW-MTL] 271.95% (거래량:1925.36, 평균:707.98) 106 | INFO:root:[KRW-LTC] 44.41% (거래량:2.14, 평균:4.81) 107 | INFO:root:[KRW-STRAT] 234.07% (거래량:283.44, 평균:121.09) 108 | INFO:root:[KRW-XRP] 0.03% (거래량:4.76, 평균:16015.26) 109 | INFO:root:[KRW-ETC] 205.69% (거래량:186.00, 평균:90.43) 110 | INFO:root:[KRW-OMG] 385.67% (거래량:117.96, 평균:30.59) 111 | INFO:root:[KRW-SNT] 379.30% (거래량:17593.24, 평균:4638.37) 112 | INFO:root:[KRW-WAVES] 1224.08% (거래량:311.57, 평균:25.45) 113 | INFO:root:[KRW-PIVX] 213.84% (거래량:5058.09, 평균:2365.36) 114 | INFO:root:[KRW-XEM] 5.54% (거래량:31.62, 평균:571.11) 115 | INFO:root:[KRW-ZEC] 49.58% (거래량:0.24, 평균:0.48) 116 | INFO:root:[KRW-XMR] 798.76% (거래량:1.79, 평균:0.22) 117 | INFO:root:[KRW-QTUM] 94.61% (거래량:155.34, 평균:164.18) 118 | INFO:root:[KRW-GNT] 212.99% (거래량:6306.25, 평균:2960.76) 119 | INFO:root:[KRW-LSK] 440.22% (거래량:18.28, 평균:4.15) 120 | INFO:root:[KRW-STEEM] 1363.72% (거래량:2401.45, 평균:176.10) 121 | INFO:root:[KRW-XLM] 287.85% (거래량:5493.67, 평균:1908.52) 122 | INFO:root:[KRW-ARDR] 90.69% (거래량:805.46, 평균:888.13) 123 | INFO:root:[KRW-KMD] 92.75% (거래량:50.00, 평균:53.91) 124 | INFO:root:[KRW-ARK] 22116.28% (거래량:5000.00, 평균:22.61) 125 | INFO:root:[KRW-STORJ] 4.95% (거래량:39.00, 평균:788.49) 126 | INFO:root:[KRW-GRS] 5.08% (거래량:38.78, 평균:763.61) 127 | INFO:root:[KRW-VTC] 35.95% (거래량:3.52, 평균:9.79) 128 | INFO:root:[KRW-REP] 337.72% (거래량:3.73, 평균:1.11) 129 | INFO:root:[KRW-EMC2] 115.74% (거래량:2595.31, 평균:2242.45) 130 | INFO:root:[KRW-ADA] 98.74% (거래량:19255.83, 평균:19500.85) 131 | INFO:root:[KRW-SBD] 458.64% (거래량:26.72, 평균:5.83) 132 | INFO:root:[KRW-POWR] 1766.31% (거래량:15665.44, 평균:886.90) 133 | INFO:root:[KRW-BTG] 158.79% (거래량:17.16, 평균:10.81) 134 | INFO:root:[KRW-ICX] 257.26% (거래량:2080.00, 평균:808.51) 135 | INFO:root:[KRW-EOS] 324.17% (거래량:1973.48, 평균:608.79) 136 | INFO:root:[KRW-STORM] 827.11% (거래량:59116.25, 평균:7147.30) 137 | INFO:root:[KRW-TRX] 1.53% (거래량:854.14, 평균:55744.80) 138 | INFO:root:[KRW-MCO] 2635.23% (거래량:58.51, 평균:2.22) 139 | INFO:root:[KRW-SC] 1.09% (거래량:225.00, 평균:20615.36) 140 | INFO:root:[KRW-GTO] 80.72% (거래량:10000.00, 평균:12388.62) 141 | INFO:root:[KRW-IGNIS] 8.78% (거래량:2368.72, 평균:26967.01) 142 | INFO:root:[KRW-ONT] 0.00% (거래량:0.00, 평균:32.97) 143 | INFO:root:[KRW-DCR] 3199.31% (거래량:5.36, 평균:0.17) 144 | INFO:root:[KRW-ZIL] 39.93% (거래량:4254.86, 평균:10654.59) 145 | INFO:root:[KRW-POLY] 212.04% (거래량:2890.00, 평균:1362.92) 146 | INFO:root:[KRW-ZRX] 0.85% (거래량:0.85, 평균:100.79) 147 | INFO:root:[KRW-SRN] 1783.89% (거래량:83093.79, 평균:4658.01) 148 | INFO:root:[KRW-LOOM] 427.69% (거래량:8313.00, 평균:1943.69) 149 | INFO:root:[KRW-BCH] 2.18% (거래량:0.11, 평균:4.92) 150 | INFO:root:[KRW-ADT] 181.69% (거래량:1612.93, 평균:887.72) 151 | INFO:root:[KRW-ADX] 895.18% (거래량:919.70, 평균:102.74) 152 | INFO:root:[KRW-BAT] 5.34% (거래량:13.77, 평균:257.84) 153 | INFO:root:[KRW-IOST] 1646.74% (거래량:17902.75, 평균:1087.16) 154 | INFO:root:[KRW-DMT] 3169.04% (거래량:10000.00, 평균:315.55) 155 | INFO:root:[KRW-RFR] 538.66% (거래량:248760.77, 평균:46181.70) 156 | INFO:root:[KRW-CVC] 183.60% (거래량:2570.32, 평균:1399.93) 157 | INFO:root:[KRW-IQ] 174.53% (거래량:18196.43, 평균:10425.78) 158 | INFO:root:[KRW-IOTA] 126.77% (거래량:96.69, 평균:76.27) 159 | INFO:root:[KRW-OST] 137.04% (거래량:3325.00, 평균:2426.31) 160 | INFO:root:[KRW-MFT] 0.00% (거래량:0.00, 평균:51043.83) 161 | INFO:root:[KRW-ONG] 618.64% (거래량:998.00, 평균:161.32) 162 | INFO:root:[KRW-GAS] 15.20% (거래량:1.17, 평균:7.70) 163 | INFO:root:[KRW-MEDX] 12.98% (거래량:1119.87, 평균:8626.25) 164 | INFO:root:[KRW-UPP] 1047.55% (거래량:50038.22, 평균:4776.70) 165 | INFO:root:[KRW-ELF] 1563.44% (거래량:23693.64, 평균:1515.48) 166 | INFO:root:[KRW-KNC] 350.26% (거래량:395.96, 평균:113.05) 167 | INFO:root:[KRW-BSV] 0.19% (거래량:0.01, 평균:4.58) 168 | INFO:root:[KRW-THETA] 1469.98% (거래량:7870.87, 평균:535.44) 169 | INFO:root:[KRW-EDR] 116.39% (거래량:3809.63, 평균:3273.07) 170 | INFO:root:[KRW-QKC] 23.29% (거래량:3378.38, 평균:14508.01) 171 | INFO:root:[KRW-CPT] 8.68% (거래량:1337.29, 평균:15405.81) 172 | INFO:root:[KRW-BTT] 3058.63% (거래량:12339450.04, 평균:403430.05) 173 | INFO:root:[KRW-MOC] 41.33% (거래량:1631.00, 평균:3946.43) 174 | INFO:root:[KRW-COSM] 1568.55% (거래량:268609.80, 평균:17124.76) 175 | INFO:root:[KRW-ENJ] 20.80% (거래량:4010.00, 평균:19279.26) 176 | INFO:root:[KRW-TFUEL] 60.35% (거래량:8156.91, 평균:13515.84) 177 | INFO:root:[KRW-MANA] 3344.05% (거래량:6042.65, 평균:180.70) 178 | INFO:root:[KRW-ANKR] 62.91% (거래량:13060.64, 평균:20759.42) 179 | INFO:root:[KRW-NPXS] 379.30% (거래량:428833.94, 평균:113057.89) 180 | INFO:root:[KRW-TTC] 878.55% (거래량:51334.31, 평균:5843.05) 181 | INFO:root:[KRW-AERGO] 13.90% (거래량:47.15, 평균:339.24) 182 | INFO:root:[KRW-ATOM] 24.46% (거래량:20.51, 평균:83.86) 183 | INFO:root:[KRW-TT] 0.54% (거래량:100.00, 평균:18352.15) 184 | INFO:root:[KRW-CRE] 9.31% (거래량:8542.41, 평균:91771.97) 185 | INFO:root:[KRW-SOLVE] 290.69% (거래량:14004.00, 평균:4817.49) 186 | INFO:root:[KRW-MBL] 94.23% (거래량:39331.87, 평균:41741.52) 187 | INFO:root:[KRW-TSHP] 28.88% (거래량:5717.36, 평균:19799.87) 188 | INFO:root:[KRW-WAXP] 17.43% (거래량:192.56, 평균:1104.74) 189 | ``` 190 | -------------------------------------------------------------------------------- /samples/get_all_price.md: -------------------------------------------------------------------------------- 1 | # 모든 코인 가격 가져오기 2 | 3 | - get_all_price.py 4 | 5 | ## 출력 6 | 7 | ```bash 8 | $ python samples/get_all_price.py 9 | INFO:root:BTC 마켓: 10 | INFO:root:BTC-ETH: 0.01767280 btc 11 | INFO:root:BTC-LTC: 0.00688000 btc 12 | INFO:root:BTC-STRAT: 0.00004005 btc 13 | INFO:root:BTC-XRP: 0.00002654 btc 14 | INFO:root:BTC-ETC: 0.00064600 btc 15 | INFO:root:BTC-OMG: 0.00011205 btc 16 | INFO:root:BTC-CVC: 0.00000415 btc 17 | INFO:root:BTC-DGB: 0.00000086 btc 18 | INFO:root:BTC-PAY: 0.00001079 btc 19 | INFO:root:BTC-SC: 0.00000018 btc 20 | INFO:root:BTC-SNT: 0.00000160 btc 21 | INFO:root:BTC-DASH: 0.00821660 btc 22 | INFO:root:BTC-XVG: 0.00000047 btc 23 | INFO:root:BTC-WAVES: 0.00011220 btc 24 | INFO:root:BTC-NMR: 0.00045285 btc 25 | INFO:root:BTC-PIVX: 0.00003537 btc 26 | INFO:root:BTC-GBYTE: 0.00229999 btc 27 | INFO:root:BTC-XEM: 0.00000503 btc 28 | INFO:root:BTC-ZEC: 0.00466225 btc 29 | INFO:root:BTC-XMR: 0.00720400 btc 30 | INFO:root:BTC-LBC: 0.00000136 btc 31 | INFO:root:BTC-QTUM: 0.00021604 btc 32 | INFO:root:BTC-GNT: 0.00000605 btc 33 | INFO:root:BTC-NXT: 0.00000155 btc 34 | INFO:root:BTC-BAT: 0.00001918 btc 35 | INFO:root:BTC-XEL: 0.00000110 btc 36 | INFO:root:BTC-LSK: 0.00011456 btc 37 | INFO:root:BTC-RDD: 0.00000011 btc 38 | INFO:root:BTC-DCT: 0.00000425 btc 39 | INFO:root:BTC-STEEM: 0.00001702 btc 40 | INFO:root:BTC-GAME: 0.00000402 btc 41 | INFO:root:BTC-FCT: 0.00033760 btc 42 | INFO:root:BTC-PTOY: 0.00000093 btc 43 | INFO:root:BTC-DCR: 0.00246666 btc 44 | INFO:root:BTC-DOGE: 0.00000025 btc 45 | INFO:root:BTC-BNT: 0.00003639 btc 46 | INFO:root:BTC-XLM: 0.00000643 btc 47 | INFO:root:BTC-PART: 0.00015497 btc 48 | INFO:root:BTC-MCO: 0.00034224 btc 49 | INFO:root:BTC-UBQ: 0.00000941 btc 50 | INFO:root:BTC-ARDR: 0.00000563 btc 51 | INFO:root:BTC-KMD: 0.00006752 btc 52 | INFO:root:BTC-ARK: 0.00002146 btc 53 | INFO:root:BTC-ADX: 0.00000807 btc 54 | INFO:root:BTC-SYS: 0.00000270 btc 55 | INFO:root:BTC-ANT: 0.00005610 btc 56 | INFO:root:BTC-MUE: 0.00000066 btc 57 | INFO:root:BTC-XDN: 0.00000007 btc 58 | INFO:root:BTC-STORJ: 0.00001530 btc 59 | INFO:root:BTC-QRL: 0.00001732 btc 60 | INFO:root:BTC-NXS: 0.00002384 btc 61 | INFO:root:BTC-GRS: 0.00002196 btc 62 | INFO:root:BTC-VTC: 0.00002787 btc 63 | INFO:root:BTC-SIB: 0.00000495 btc 64 | INFO:root:BTC-REP: 0.00083737 btc 65 | INFO:root:BTC-VIA: 0.00002518 btc 66 | INFO:root:BTC-SWT: 0.00000589 btc 67 | INFO:root:BTC-MONA: 0.00012930 btc 68 | INFO:root:BTC-AMP: 0.00000045 btc 69 | INFO:root:BTC-HMQ: 0.00000064 btc 70 | INFO:root:BTC-RLC: 0.00002069 btc 71 | INFO:root:BTC-BLOCK: 0.00013318 btc 72 | INFO:root:BTC-MEME: 0.00000065 btc 73 | INFO:root:BTC-OK: 0.00000403 btc 74 | INFO:root:BTC-XZC: 0.00058023 btc 75 | INFO:root:BTC-ADT: 0.00000032 btc 76 | INFO:root:BTC-FTC: 0.00000149 btc 77 | INFO:root:BTC-ION: 0.00000585 btc 78 | INFO:root:BTC-GNO: 0.00148443 btc 79 | INFO:root:BTC-EMC2: 0.00000565 btc 80 | INFO:root:BTC-EXCL: 0.00000760 btc 81 | INFO:root:BTC-EXP: 0.00000285 btc 82 | INFO:root:BTC-VRC: 0.00000553 btc 83 | INFO:root:BTC-BURST: 0.00000041 btc 84 | INFO:root:BTC-SHIFT: 0.00002100 btc 85 | INFO:root:BTC-BLK: 0.00000539 btc 86 | INFO:root:BTC-ZEN: 0.00048154 btc 87 | INFO:root:BTC-RADS: 0.00004760 btc 88 | INFO:root:BTC-IOP: 0.00000237 btc 89 | INFO:root:BTC-NAV: 0.00001082 btc 90 | INFO:root:BTC-ADA: 0.00000461 btc 91 | INFO:root:BTC-MANA: 0.00000324 btc 92 | INFO:root:BTC-SBD: 0.00008348 btc 93 | INFO:root:BTC-RCN: 0.00000152 btc 94 | INFO:root:BTC-VIB: 0.00000175 btc 95 | INFO:root:BTC-POWR: 0.00000572 btc 96 | INFO:root:BTC-ENG: 0.00003413 btc 97 | INFO:root:BTC-UKG: 0.00000216 btc 98 | INFO:root:BTC-DNT: 0.00000069 btc 99 | INFO:root:BTC-IGNIS: 0.00000327 btc 100 | INFO:root:BTC-SRN: 0.00000101 btc 101 | INFO:root:BTC-ZRX: 0.00001643 btc 102 | INFO:root:BTC-VEE: 0.00000018 btc 103 | INFO:root:BTC-BCPT: 0.00000308 btc 104 | INFO:root:BTC-TRX: 0.00000160 btc 105 | INFO:root:BTC-TUSD: 0.00010364 btc 106 | INFO:root:BTC-LRC: 0.00000343 btc 107 | INFO:root:BTC-RVR: 0.00000063 btc 108 | INFO:root:BTC-UP: 0.00000046 btc 109 | INFO:root:BTC-DMT: 0.00000901 btc 110 | INFO:root:BTC-POLY: 0.00000370 btc 111 | INFO:root:BTC-PRO: 0.00001731 btc 112 | INFO:root:BTC-BLT: 0.00000340 btc 113 | INFO:root:BTC-STORM: 0.00000016 btc 114 | INFO:root:BTC-AID: 0.00000114 btc 115 | INFO:root:BTC-NGC: 0.00000197 btc 116 | INFO:root:BTC-GTO: 0.00000213 btc 117 | INFO:root:BTC-OCN: 0.00000011 btc 118 | INFO:root:BTC-TUBE: 0.00000119 btc 119 | INFO:root:BTC-CMCT: 0.00000006 btc 120 | INFO:root:BTC-BCH: 0.02924000 btc 121 | INFO:root:BTC-BKX: 0.00000068 btc 122 | INFO:root:BTC-MFT: 0.00000010 btc 123 | INFO:root:BTC-LOOM: 0.00000290 btc 124 | INFO:root:BTC-RFR: 0.00000010 btc 125 | INFO:root:BTC-RVN: 0.00000323 btc 126 | INFO:root:BTC-BFT: 0.00000204 btc 127 | INFO:root:BTC-GO: 0.00000102 btc 128 | INFO:root:BTC-UPP: 0.00000134 btc 129 | INFO:root:BTC-ENJ: 0.00000748 btc 130 | INFO:root:BTC-MET: 0.00006374 btc 131 | INFO:root:BTC-HYDRO: 0.00000008 btc 132 | INFO:root:BTC-CRW: 0.00000516 btc 133 | INFO:root:BTC-DTA: 0.00000006 btc 134 | INFO:root:BTC-EDR: 0.00000063 btc 135 | INFO:root:BTC-BOXX: 0.00000231 btc 136 | INFO:root:BTC-IHT: 0.00000038 btc 137 | INFO:root:BTC-XHV: 0.00002958 btc 138 | INFO:root:BTC-MTL: 0.00003948 btc 139 | INFO:root:BTC-PMA: 0.00000003 btc 140 | INFO:root:BTC-PAL: 0.00000011 btc 141 | INFO:root:BTC-PAX: 0.00010389 btc 142 | INFO:root:BTC-MOC: 0.00000204 btc 143 | INFO:root:BTC-NPXS: 0.00000004 btc 144 | INFO:root:BTC-ZIL: 0.00000073 btc 145 | INFO:root:BTC-OST: 0.00000113 btc 146 | INFO:root:BTC-MEDX: 0.00000041 btc 147 | INFO:root:BTC-SPC: 0.00000028 btc 148 | INFO:root:BTC-BSV: 0.01338438 btc 149 | INFO:root:BTC-IOST: 0.00000073 btc 150 | INFO:root:BTC-XNK: 0.00000015 btc 151 | INFO:root:BTC-NCASH: 0.00000011 btc 152 | INFO:root:BTC-JNT: 0.00000344 btc 153 | INFO:root:BTC-LBA: 0.00000194 btc 154 | INFO:root:BTC-DENT: 0.00000005 btc 155 | INFO:root:BTC-DRGN: 0.00000513 btc 156 | INFO:root:BTC-BTM: 0.00000804 btc 157 | INFO:root:BTC-ELF: 0.00000818 btc 158 | INFO:root:BTC-BTT: 0.00000006 btc 159 | INFO:root:BTC-VITE: 0.00000206 btc 160 | INFO:root:BTC-IOTX: 0.00000046 btc 161 | INFO:root:BTC-BTU: 0.00003180 btc 162 | INFO:root:BTC-SOLVE: 0.00001370 btc 163 | INFO:root:BTC-NKN: 0.00000278 btc 164 | INFO:root:BTC-QNT: 0.00058200 btc 165 | INFO:root:BTC-CTXC: 0.00000971 btc 166 | INFO:root:BTC-SPND: 0.00000032 btc 167 | INFO:root:BTC-META: 0.00000092 btc 168 | INFO:root:BTC-SERV: 0.00000049 btc 169 | INFO:root:BTC-ANKR: 0.00000043 btc 170 | INFO:root:BTC-CRO: 0.00000404 btc 171 | INFO:root:BTC-BTS: 0.00000335 btc 172 | INFO:root:BTC-FSN: 0.00007262 btc 173 | INFO:root:BTC-TTC: 0.00000623 btc 174 | INFO:root:BTC-VBK: 0.00000181 btc 175 | INFO:root:BTC-ORBS: 0.00000136 btc 176 | INFO:root:BTC-HST: 0.00000061 btc 177 | INFO:root:BTC-AERGO: 0.00000783 btc 178 | INFO:root:BTC-PI: 0.00000072 btc 179 | INFO:root:BTC-VDX: 0.00000022 btc 180 | INFO:root:BTC-COSM: 0.00000125 btc 181 | INFO:root:BTC-ATOM: 0.00022996 btc 182 | INFO:root:BTC-STPT: 0.00000186 btc 183 | INFO:root:BTC-CPT: 0.00000034 btc 184 | INFO:root:BTC-LAMB: 0.00001747 btc 185 | INFO:root:BTC-EOS: 0.00033623 btc 186 | INFO:root:BTC-LUNA: 0.00011920 btc 187 | INFO:root:BTC-DAI: 0.00010306 btc 188 | INFO:root:BTC-MKR: 0.05029943 btc 189 | INFO:root:BTC-BORA: 0.00000204 btc 190 | INFO:root:BTC-TSHP: 0.00000478 btc 191 | INFO:root:BTC-WAXP: 0.00000449 btc 192 | INFO:root:KRW 마켓: 193 | INFO:root:KRW-BTC: 11642000.0 원 194 | INFO:root:KRW-DASH: 96480.0 원 195 | INFO:root:KRW-ETH: 205750.0 원 196 | INFO:root:KRW-NEO: 10560.0 원 197 | INFO:root:KRW-MTL: 459.0 원 198 | INFO:root:KRW-LTC: 80050.0 원 199 | INFO:root:KRW-STRAT: 465.0 원 200 | INFO:root:KRW-XRP: 310.0 원 201 | INFO:root:KRW-ETC: 7550.0 원 202 | INFO:root:KRW-OMG: 1300.0 원 203 | INFO:root:KRW-SNT: 18.7 원 204 | INFO:root:KRW-WAVES: 1295.0 원 205 | INFO:root:KRW-PIVX: 405.0 원 206 | INFO:root:KRW-XEM: 58.4 원 207 | INFO:root:KRW-ZEC: 54230.0 원 208 | INFO:root:KRW-XMR: 83960.0 원 209 | INFO:root:KRW-QTUM: 2520.0 원 210 | INFO:root:KRW-GNT: 70.2 원 211 | INFO:root:KRW-LSK: 1335.0 원 212 | INFO:root:KRW-STEEM: 200.0 원 213 | INFO:root:KRW-XLM: 74.7 원 214 | INFO:root:KRW-ARDR: 65.9 원 215 | INFO:root:KRW-KMD: 787.0 원 216 | INFO:root:KRW-ARK: 250.0 원 217 | INFO:root:KRW-STORJ: 178.0 원 218 | INFO:root:KRW-GRS: 256.0 원 219 | INFO:root:KRW-VTC: 328.0 원 220 | INFO:root:KRW-REP: 9705.0 원 221 | INFO:root:KRW-EMC2: 66.0 원 222 | INFO:root:KRW-ADA: 53.4 원 223 | INFO:root:KRW-SBD: 977.0 원 224 | INFO:root:KRW-POWR: 66.7 원 225 | INFO:root:KRW-BTG: 13030.0 원 226 | INFO:root:KRW-ICX: 251.0 원 227 | INFO:root:KRW-EOS: 3905.0 원 228 | INFO:root:KRW-STORM: 1.87 원 229 | INFO:root:KRW-TRX: 18.8 원 230 | INFO:root:KRW-MCO: 4035.0 원 231 | INFO:root:KRW-SC: 2.19 원 232 | INFO:root:KRW-GTO: 24.4 원 233 | INFO:root:KRW-IGNIS: 37.6 원 234 | INFO:root:KRW-ONT: 853.0 원 235 | INFO:root:KRW-DCR: 28440.0 원 236 | INFO:root:KRW-ZIL: 8.45 원 237 | INFO:root:KRW-POLY: 43.4 원 238 | INFO:root:KRW-ZRX: 192.0 원 239 | INFO:root:KRW-SRN: 12.0 원 240 | INFO:root:KRW-LOOM: 33.6 원 241 | INFO:root:KRW-BCH: 339500.0 원 242 | INFO:root:KRW-ADT: 3.66 원 243 | INFO:root:KRW-ADX: 93.4 원 244 | INFO:root:KRW-BAT: 223.0 원 245 | INFO:root:KRW-IOST: 8.4 원 246 | INFO:root:KRW-DMT: 104.0 원 247 | INFO:root:KRW-RFR: 1.2 원 248 | INFO:root:KRW-CVC: 48.4 원 249 | INFO:root:KRW-IQ: 2.78 원 250 | INFO:root:KRW-IOTA: 290.0 원 251 | INFO:root:KRW-OST: 13.1 원 252 | INFO:root:KRW-MFT: 1.21 원 253 | INFO:root:KRW-ONG: 218.0 원 254 | INFO:root:KRW-GAS: 1760.0 원 255 | INFO:root:KRW-MEDX: 4.9 원 256 | INFO:root:KRW-UPP: 15.2 원 257 | INFO:root:KRW-ELF: 95.4 원 258 | INFO:root:KRW-KNC: 194.0 원 259 | INFO:root:KRW-BSV: 156100.0 원 260 | INFO:root:KRW-THETA: 135.0 원 261 | INFO:root:KRW-EDR: 7.4 원 262 | INFO:root:KRW-QKC: 15.8 원 263 | INFO:root:KRW-CPT: 3.95 원 264 | INFO:root:KRW-BTT: 0.63 원 265 | INFO:root:KRW-MOC: 23.8 원 266 | INFO:root:KRW-COSM: 13.9 원 267 | INFO:root:KRW-ENJ: 87.2 원 268 | INFO:root:KRW-TFUEL: 5.77 원 269 | INFO:root:KRW-MANA: 37.4 원 270 | INFO:root:KRW-ANKR: 5.07 원 271 | INFO:root:KRW-NPXS: 0.47 원 272 | INFO:root:KRW-TTC: 70.7 원 273 | INFO:root:KRW-AERGO: 92.3 원 274 | INFO:root:KRW-ATOM: 2680.0 원 275 | INFO:root:KRW-TT: 5.19 원 276 | INFO:root:KRW-CRE: 11.0 원 277 | INFO:root:KRW-SOLVE: 159.0 원 278 | INFO:root:KRW-MBL: 2.05 원 279 | INFO:root:KRW-TSHP: 55.8 원 280 | INFO:root:KRW-WAXP: 52.5 원 281 | INFO:root:ETH 마켓: 282 | INFO:root:ETH-LTC: 0.39029110 eth 283 | INFO:root:ETH-STRAT: 0.00228000 eth 284 | INFO:root:ETH-XRP: 0.00149887 eth 285 | INFO:root:ETH-ETC: 0.03664899 eth 286 | INFO:root:ETH-OMG: 0.00640000 eth 287 | INFO:root:ETH-CVC: 0.00023571 eth 288 | INFO:root:ETH-DGB: 0.00004920 eth 289 | INFO:root:ETH-PAY: 0.00060277 eth 290 | INFO:root:ETH-SC: 0.00001065 eth 291 | INFO:root:ETH-SNT: 0.00009010 eth 292 | INFO:root:ETH-DASH: 0.46400000 eth 293 | INFO:root:ETH-WAVES: 0.00636000 eth 294 | INFO:root:ETH-XEM: 0.00028404 eth 295 | INFO:root:ETH-ZEC: 0.26445614 eth 296 | INFO:root:ETH-XMR: 0.40700000 eth 297 | INFO:root:ETH-QTUM: 0.01225621 eth 298 | INFO:root:ETH-GNT: 0.00034222 eth 299 | INFO:root:ETH-BAT: 0.00108155 eth 300 | INFO:root:ETH-BNT: 0.00200683 eth 301 | INFO:root:ETH-XLM: 0.00036618 eth 302 | INFO:root:ETH-MCO: 0.01919387 eth 303 | INFO:root:ETH-ADX: 0.00045567 eth 304 | INFO:root:ETH-ANT: 0.00322001 eth 305 | INFO:root:ETH-REP: 0.04727871 eth 306 | INFO:root:ETH-GNO: 0.08233861 eth 307 | INFO:root:ETH-MANA: 0.00018331 eth 308 | INFO:root:ETH-VIB: 0.00009747 eth 309 | INFO:root:ETH-POWR: 0.00032100 eth 310 | INFO:root:ETH-SRN: 0.00005807 eth 311 | INFO:root:ETH-ZRX: 0.00093870 eth 312 | INFO:root:ETH-TRX: 0.00009057 eth 313 | INFO:root:ETH-TUSD: 0.00594000 eth 314 | INFO:root:ETH-ADA: 0.00026062 eth 315 | INFO:root:ETH-ENG: 0.00192000 eth 316 | INFO:root:ETH-UKG: 0.00012067 eth 317 | INFO:root:ETH-DMT: 0.00051847 eth 318 | INFO:root:ETH-STORM: 0.00000919 eth 319 | INFO:root:ETH-OCN: 0.00000642 eth 320 | INFO:root:ETH-BCH: 1.64912201 eth 321 | INFO:root:ETH-WAXP: 0.00027700 eth 322 | INFO:root:USDT 마켓: 323 | INFO:root:USDT-BTC: 9601.951 usdt 324 | INFO:root:USDT-ETH: 169.612 usdt 325 | INFO:root:USDT-LTC: 66.360 usdt 326 | INFO:root:USDT-XRP: 0.254 usdt 327 | INFO:root:USDT-ETC: 6.192 usdt 328 | INFO:root:USDT-DASH: 79.000 usdt 329 | INFO:root:USDT-ZEC: 44.627 usdt 330 | INFO:root:USDT-XMR: 69.189 usdt 331 | INFO:root:USDT-OMG: 1.077 usdt 332 | INFO:root:USDT-XVG: 0.005 usdt 333 | INFO:root:USDT-ADA: 0.044 usdt 334 | INFO:root:USDT-TUSD: 0.998 usdt 335 | INFO:root:USDT-SC: 0.002 usdt 336 | INFO:root:USDT-TRX: 0.015 usdt 337 | INFO:root:USDT-DCR: 23.347 usdt 338 | INFO:root:USDT-BCH: 281.091 usdt 339 | INFO:root:USDT-DGB: 0.008 usdt 340 | INFO:root:USDT-DOGE: 0.002 usdt 341 | INFO:root:USDT-ZRX: 0.158 usdt 342 | INFO:root:USDT-RVN: 0.031 usdt 343 | INFO:root:USDT-BAT: 0.179 usdt 344 | INFO:root:USDT-PAX: 0.995 usdt 345 | ``` -------------------------------------------------------------------------------- /upbitpy/upbitpy.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import json 3 | import time 4 | import requests 5 | import jwt 6 | import logging 7 | from datetime import datetime 8 | from urllib.parse import urlencode 9 | 10 | 11 | class Upbitpy(): 12 | """ 13 | Upbit API 14 | https://docs.upbit.com/v1.0/reference 15 | """ 16 | 17 | def __init__(self, access_key=None, secret=None): 18 | ''' 19 | Constructor 20 | access_key, secret이 없으면 인증가능 요청(EXCHANGE API)은 사용할 수 없음 21 | :param str access_key: 발급 받은 acccess key 22 | :param str secret: 발급 받은 secret 23 | ''' 24 | self.access_key = access_key 25 | self.secret = secret 26 | self.remaining_req = dict() 27 | self.markets = self._load_markets() 28 | 29 | ############################################################### 30 | # EXCHANGE API 31 | ############################################################### 32 | 33 | def get_accounts(self): 34 | ''' 35 | 전체 계좌 조회 36 | 내가 보유한 자산 리스트를 보여줍니다. 37 | https://docs.upbit.com/v1.0/reference#%EC%9E%90%EC%82%B0-%EC%A0%84%EC%B2%B4-%EC%A1%B0%ED%9A%8C 38 | :return: json array 39 | ''' 40 | URL = 'https://api.upbit.com/v1/accounts' 41 | return self._get(URL, self._get_headers()) 42 | 43 | def get_chance(self, market): 44 | ''' 45 | 주문 가능 정보 46 | 마켓별 주문 가능 정보를 확인한다. 47 | https://docs.upbit.com/v1.0/reference#%EC%A3%BC%EB%AC%B8-%EA%B0%80%EB%8A%A5-%EC%A0%95%EB%B3%B4 48 | :param str market: Market ID 49 | :return: json object 50 | ''' 51 | URL = 'https://api.upbit.com/v1/orders/chance' 52 | if market not in self.markets: 53 | logging.error('invalid market: %s' % market) 54 | raise Exception('invalid market: %s' % market) 55 | data = {'market': market} 56 | return self._get(URL, self._get_headers(data), data) 57 | 58 | def get_order(self, uuid): 59 | ''' 60 | 개별 주문 조회 61 | 주문 UUID 를 통해 개별 주문건을 조회한다. 62 | https://docs.upbit.com/v1.0/reference#%EA%B0%9C%EB%B3%84-%EC%A3%BC%EB%AC%B8-%EC%A1%B0%ED%9A%8C 63 | :param str uuid: 주문 UUID 64 | :return: json object 65 | ''' 66 | URL = 'https://api.upbit.com/v1/order' 67 | try: 68 | data = {'uuid': uuid} 69 | return self._get(URL, self._get_headers(data), data) 70 | except Exception as e: 71 | logging.error(e) 72 | raise Exception(e) 73 | 74 | def get_orders(self, market, state, page=1, order_by='asc'): 75 | ''' 76 | 주문 리스트 조회 77 | 주문 리스트를 조회한다. 78 | https://docs.upbit.com/v1.0/reference#%EC%A3%BC%EB%AC%B8-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%A1%B0%ED%9A%8C 79 | :param str market: Market ID 80 | :param str state: 주문 상태 81 | wait:체결 대기(default) 82 | done: 체결 완료 83 | cancel: 주문 취소 84 | :param int page: 페이지 수, default: 1 85 | :param str order_by: 정렬 방식 86 | asc: 오름차순(default) 87 | desc:내림차순 88 | :return: json array 89 | ''' 90 | URL = 'https://api.upbit.com/v1/orders' 91 | if market not in self.markets: 92 | logging.error('invalid market: %s' % market) 93 | raise Exception('invalid market: %s' % market) 94 | 95 | if state not in ['wait', 'done', 'cancel']: 96 | logging.error('invalid state: %s' % state) 97 | raise Exception('invalid state: %s' % state) 98 | 99 | if order_by not in ['asc', 'desc']: 100 | logging.error('invalid order_by: %s' % order_by) 101 | raise Exception('invalid order_by: %s' % order_by) 102 | 103 | data = { 104 | 'market': market, 105 | 'state': state, 106 | 'page': page, 107 | 'order_by': order_by 108 | } 109 | return self._get(URL, self._get_headers(data), data) 110 | 111 | def order(self, market, side, volume, price): 112 | ''' 113 | 주문하기 114 | 주문 요청을 한다. 115 | https://docs.upbit.com/v1.0/reference#%EC%A3%BC%EB%AC%B8%ED%95%98%EA%B8%B0-1 116 | :param str market: 마켓 ID (필수) 117 | :param str side: 주문 종류 (필수) 118 | bid : 매수 119 | ask : 매도 120 | :param str volume: 주문량 (필수) 121 | :param str price: 유닛당 주문 가격. (필수) 122 | ex) KRW-BTC 마켓에서 1BTC당 1,000 KRW로 거래할 경우, 값은 1000 이 된다. 123 | :return: json object 124 | ''' 125 | URL = 'https://api.upbit.com/v1/orders' 126 | if market not in self.markets: 127 | logging.error('invalid market: %s' % market) 128 | raise Exception('invalid market: %s' % market) 129 | 130 | if side not in ['bid', 'ask']: 131 | logging.error('invalid side: %s' % side) 132 | raise Exception('invalid side: %s' % side) 133 | 134 | if market.startswith('KRW') and not self._is_valid_price(price): 135 | logging.error('invalid price: %.2f' % price) 136 | raise Exception('invalid price: %.2f' % price) 137 | 138 | data = { 139 | 'market': market, 140 | 'side': side, 141 | 'volume': str(volume), 142 | 'price': str(price), 143 | 'ord_type': 'limit' 144 | } 145 | return self._post(URL, self._get_headers(data), data) 146 | 147 | def cancel_order(self, uuid): 148 | ''' 149 | 주문 취소 150 | 주문 UUID를 통해 해당 주문을 취소한다. 151 | https://docs.upbit.com/v1.0/reference#%EC%A3%BC%EB%AC%B8-%EC%B7%A8%EC%86%8C 152 | :param str uuid: 주문 UUID 153 | :return: json object 154 | ''' 155 | URL = 'https://api.upbit.com/v1/order' 156 | data = {'uuid': uuid} 157 | return self._delete(URL, self._get_headers(data), data) 158 | 159 | def get_withraws(self, currency, state, limit): 160 | ''' 161 | 출금 리스트 조회 162 | https://docs.upbit.com/v1.0/reference#%EC%A0%84%EC%B2%B4-%EC%B6%9C%EA%B8%88-%EC%A1%B0%ED%9A%8C 163 | :param str currency: Currency 코드 164 | :param str state: 출금 상태 165 | submitting : 처리 중 166 | submitted : 처리 완료 167 | almost_accepted : 출금대기중 168 | rejected : 거부 169 | accepted : 승인됨 170 | processing : 처리 중 171 | done : 완료 172 | canceled : 취소됨 173 | :param int limit: 갯수 제한 174 | :return: json array 175 | ''' 176 | LIMIT_MAX = 100 177 | VALID_STATE = ['submitting', 'submitted', 'almost_accepted', 178 | 'rejected', 'accepted', 'processing', 'done', 'canceled'] 179 | URL = 'https://api.upbit.com/v1/withdraws' 180 | data = {} 181 | if currency is not None: 182 | data['currency'] = currency 183 | if state is not None: 184 | if state not in VALID_STATE: 185 | logging.error('invalid state(%s)' % state) 186 | raise Exception('invalid state(%s)' % state) 187 | data['state'] = state 188 | if limit is not None: 189 | if limit <= 0 or limit > LIMIT_MAX: 190 | logging.error('invalid limit(%d)' % limit) 191 | raise Exception('invalid limit(%d)' % limit) 192 | data['limit'] = limit 193 | return self._get(URL, self._get_headers(data), data) 194 | 195 | def get_withraw(self, uuid): 196 | ''' 197 | 개별 출금 조회 198 | 출금 UUID를 통해 개별 출금 정보를 조회한다. 199 | https://docs.upbit.com/v1.0/reference#%EA%B0%9C%EB%B3%84-%EC%B6%9C%EA%B8%88-%EC%A1%B0%ED%9A%8C 200 | :param str uuid: 출금 UUID 201 | :return: json object 202 | ''' 203 | URL = 'https://api.upbit.com/v1/withdraw' 204 | data = {'uuid': uuid} 205 | return self._get(URL, self._get_headers(data), data) 206 | 207 | def get_withraws_chance(self, currency): 208 | ''' 209 | 출금 가능 정보 210 | 해당 통화의 가능한 출금 정보를 확인한다. 211 | https://docs.upbit.com/v1.0/reference#%EC%B6%9C%EA%B8%88-%EA%B0%80%EB%8A%A5-%EC%A0%95%EB%B3%B4 212 | :param str currency: Currency symbol 213 | :return: json object 214 | ''' 215 | URL = 'https://api.upbit.com/v1/withdraws/chance' 216 | data = {'currency': currency} 217 | return self._get(URL, self._get_headers(data), data) 218 | 219 | def withdraws_coin(self, currency, amount, address, secondary_address=None): 220 | ''' 221 | 코인 출금하기 222 | 코인 출금을 요청한다. 223 | https://docs.upbit.com/v1.0/reference#%EC%BD%94%EC%9D%B8-%EC%B6%9C%EA%B8%88%ED%95%98%EA%B8%B0 224 | :param str currency: Currency symbol 225 | :param str amount: 출금 코인 수량 226 | :param str address: 출금 지갑 주소 227 | :param str secondary_address: 2차 출금 주소 (필요한 코인에 한해서) 228 | ''' 229 | URL = 'https://api.upbit.com/v1/withdraws/coin' 230 | data = { 231 | 'currency': currency, 232 | 'amount': amount, 233 | 'address': address 234 | } 235 | if secondary_address is not None: 236 | data['secondary_address'] = secondary_address 237 | return self._post(URL, self._get_headers(data), data) 238 | 239 | def withdraws_krw(self, amount): 240 | ''' 241 | 원화 출금하기 242 | 원화 출금을 요청한다. 등록된 출금 계좌로 출금된다. 243 | https://docs.upbit.com/v1.0/reference#%EC%9B%90%ED%99%94-%EC%B6%9C%EA%B8%88%ED%95%98%EA%B8%B0 244 | :param str amount: 출금 원화 수량 245 | ''' 246 | URL = 'https://api.upbit.com/v1/withdraws/krw' 247 | data = {'amount': amount} 248 | return self._post(URL, self._get_headers(data), data) 249 | 250 | def get_deposits(self, currency=None, limit=None, page=None, order_by=None): 251 | ''' 252 | 입금 리스트 조회 253 | https://docs.upbit.com/v1.0/reference#%EC%9E%85%EA%B8%88-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%A1%B0%ED%9A%8C 254 | :param str currency: Currency 코드 255 | :param int limit: 페이지당 개수 256 | :param int page: 페이지 번호 257 | :param str order_by: 정렬 방식 258 | :return: json array 259 | ''' 260 | URL = 'https://api.upbit.com/v1/deposits' 261 | data = {} 262 | if currency is not None: 263 | data['currency'] = currency 264 | if limit is not None: 265 | data['limit'] = limit 266 | if page is not None: 267 | data['page'] = page 268 | if order_by is not None: 269 | data['order_by'] = order_by 270 | return self._get(URL, self._get_headers(data), data) 271 | 272 | def get_deposit(self, uuid): 273 | ''' 274 | 개별 입금 조회 275 | https://docs.upbit.com/v1.0/reference#%EA%B0%9C%EB%B3%84-%EC%9E%85%EA%B8%88-%EC%A1%B0%ED%9A%8C 276 | :param str uuid: 개별 입금의 UUID 277 | :return: json object 278 | ''' 279 | URL = 'https://api.upbit.com/v1/deposit' 280 | data = {'uuid': uuid} 281 | return self._get(URL, self._get_headers(data), data) 282 | 283 | ############################################################### 284 | # QUOTATION API 285 | ############################################################### 286 | 287 | def get_market_all(self): 288 | ''' 289 | 마켓 코드 조회 290 | 업비트에서 거래 가능한 마켓 목록 291 | https://docs.upbit.com/v1.0/reference#%EB%A7%88%EC%BC%93-%EC%BD%94%EB%93%9C-%EC%A1%B0%ED%9A%8C 292 | :return: json array 293 | ''' 294 | URL = 'https://api.upbit.com/v1/market/all' 295 | return self._get(URL) 296 | 297 | def get_minutes_candles(self, unit, market, to=None, count=None): 298 | ''' 299 | 분(Minute) 캔들 300 | https://docs.upbit.com/v1.0/reference#%EB%B6%84minute-%EC%BA%94%EB%93%A4-1 301 | :param int unit: 분 단위. 가능한 값 : 1, 3, 5, 15, 10, 30, 60, 240 302 | :param str market: 마켓 코드 (ex. KRW-BTC, BTC-BCC) 303 | :param str to: 마지막 캔들 시각 (exclusive). 포맷 : yyyy-MM-dd'T'HH:mm:ssXXX. 비워서 요청시 가장 최근 캔들 304 | :param int count: 캔들 개수(최대 200개까지 요청 가능) 305 | :return: json array 306 | ''' 307 | URL = 'https://api.upbit.com/v1/candles/minutes/%s' % str(unit) 308 | if unit not in [1, 3, 5, 10, 15, 30, 60, 240]: 309 | logging.error('invalid unit: %s' % str(unit)) 310 | raise Exception('invalid unit: %s' % str(unit)) 311 | if market not in self.markets: 312 | logging.error('invalid market: %s' % market) 313 | raise Exception('invalid market: %s' % market) 314 | 315 | params = {'market': market} 316 | if to is not None: 317 | params['to'] = to 318 | if count is not None: 319 | params['count'] = count 320 | return self._get(URL, params=params) 321 | 322 | def get_days_candles(self, market, to=None, count=None): 323 | ''' 324 | 일(Day) 캔들 325 | https://docs.upbit.com/v1.0/reference#%EC%9D%BCday-%EC%BA%94%EB%93%A4-1 326 | :param str market: 마켓 코드 (ex. KRW-BTC, BTC-BCC) 327 | :param str to: 마지막 캔들 시각 (exclusive). 포맷 : yyyy-MM-dd'T'HH:mm:ssXXX. 비워서 요청시 가장 최근 캔들 328 | :param int count: 캔들 개수 329 | :return: json array 330 | ''' 331 | URL = 'https://api.upbit.com/v1/candles/days' 332 | if market not in self.markets: 333 | logging.error('invalid market: %s' % market) 334 | raise Exception('invalid market: %s' % market) 335 | 336 | params = {'market': market} 337 | if to is not None: 338 | params['to'] = to 339 | if count is not None: 340 | params['count'] = count 341 | return self._get(URL, params=params) 342 | 343 | def get_weeks_candles(self, market, to=None, count=None): 344 | ''' 345 | 주(Week) 캔들 346 | https://docs.upbit.com/v1.0/reference#%EC%A3%BCweek-%EC%BA%94%EB%93%A4-1 347 | :param str market: 마켓 코드 (ex. KRW-BTC, BTC-BCC) 348 | :param str to: 마지막 캔들 시각 (exclusive). 포맷 : yyyy-MM-dd'T'HH:mm:ssXXX. 비워서 요청시 가장 최근 캔들 349 | :param int count: 캔들 개수 350 | :return: json array 351 | ''' 352 | URL = 'https://api.upbit.com/v1/candles/weeks' 353 | if market not in self.markets: 354 | logging.error('invalid market: %s' % market) 355 | raise Exception('invalid market: %s' % market) 356 | params = {'market': market} 357 | if to is not None: 358 | params['to'] = to 359 | if count is not None: 360 | params['count'] = count 361 | return self._get(URL, params=params) 362 | 363 | def get_months_candles(self, market, to=None, count=None): 364 | ''' 365 | 월(Month) 캔들 366 | https://docs.upbit.com/v1.0/reference#%EC%9B%94month-%EC%BA%94%EB%93%A4-1 367 | :param str market: 마켓 코드 (ex. KRW-BTC, BTC-BCC) 368 | :param str to: 마지막 캔들 시각 (exclusive). 포맷 : yyyy-MM-dd'T'HH:mm:ssXXX. 비워서 요청시 가장 최근 캔들 369 | :param int count: 캔들 개수 370 | :return: json array 371 | ''' 372 | 373 | URL = 'https://api.upbit.com/v1/candles/months' 374 | if market not in self.markets: 375 | logging.error('invalid market: %s' % market) 376 | raise Exception('invalid market: %s' % market) 377 | params = {'market': market} 378 | if to is not None: 379 | params['to'] = to 380 | if count is not None: 381 | params['count'] = count 382 | return self._get(URL, params=params) 383 | 384 | def get_trades_ticks(self, market, to=None, count=None, cursor=None): 385 | ''' 386 | 당일 체결 내역 387 | https://docs.upbit.com/v1.0/reference#%EC%8B%9C%EC%84%B8-%EC%B2%B4%EA%B2%B0-%EC%A1%B0%ED%9A%8C 388 | :param str market: 마켓 코드 (ex. KRW-BTC, BTC-BCC) 389 | :param str to: 마지막 체결 시각. 형식 : [HHmmss 또는 HH:mm:ss]. 비워서 요청시 가장 최근 데이터 390 | :param int count: 체결 개수 391 | :param str cursor: 페이지네이션 커서 (sequentialId) 392 | :return: json array 393 | ''' 394 | URL = 'https://api.upbit.com/v1/trades/ticks' 395 | if market not in self.markets: 396 | logging.error('invalid market: %s' % market) 397 | raise Exception('invalid market: %s' % market) 398 | params = {'market': market} 399 | if to is not None: 400 | params['to'] = to 401 | if count is not None: 402 | params['count'] = count 403 | if cursor is not None: 404 | params['cursor'] = cursor 405 | return self._get(URL, params=params) 406 | 407 | def get_ticker(self, markets): 408 | ''' 409 | 현재가 정보 410 | 요청 당시 종목의 스냅샷을 반환한다. 411 | https://docs.upbit.com/v1.0/reference#%EC%8B%9C%EC%84%B8-ticker-%EC%A1%B0%ED%9A%8C 412 | :param str[] markets: 마켓 코드 리스트 (ex. KRW-BTC, BTC-BCC) 413 | :return: json array 414 | ''' 415 | URL = 'https://api.upbit.com/v1/ticker' 416 | if not isinstance(markets, list): 417 | logging.error('invalid parameter: markets should be list') 418 | raise Exception('invalid parameter: markets should be list') 419 | 420 | if len(markets) == 0: 421 | logging.error('invalid parameter: no markets') 422 | raise Exception('invalid parameter: no markets') 423 | 424 | for market in markets: 425 | if market not in self.markets: 426 | logging.error('invalid market: %s' % market) 427 | raise Exception('invalid market: %s' % market) 428 | 429 | markets_data = markets[0] 430 | for market in markets[1:]: 431 | markets_data += ',%s' % market 432 | params = {'markets': markets_data} 433 | return self._get(URL, params=params) 434 | 435 | def get_orderbook(self, markets): 436 | ''' 437 | 호가 정보 조회 438 | https://docs.upbit.com/v1.0/reference#%ED%98%B8%EA%B0%80-%EC%A0%95%EB%B3%B4-%EC%A1%B0%ED%9A%8C 439 | :param str[] markets: 마켓 코드 목록 리스트 (ex. KRW-BTC,KRW-ADA) 440 | :return: json array 441 | ''' 442 | URL = 'https://api.upbit.com/v1/orderbook?' 443 | if not isinstance(markets, list): 444 | logging.error('invalid parameter: markets should be list') 445 | raise Exception('invalid parameter: markets should be list') 446 | 447 | if len(markets) == 0: 448 | logging.error('invalid parameter: no markets') 449 | raise Exception('invalid parameter: no markets') 450 | 451 | for market in markets: 452 | if market not in self.markets: 453 | logging.error('invalid market: %s' % market) 454 | raise Exception('invalid market: %s' % market) 455 | 456 | markets_data = markets[0] 457 | for market in markets[1:]: 458 | markets_data += ',%s' % market 459 | params = {'markets': markets_data} 460 | return self._get(URL, params=params) 461 | 462 | def get_remaining_req(self): 463 | ''' 464 | 요청 수 제한 465 | https://docs.upbit.com/docs/user-request-guide 466 | :return: dict 467 | ex) {'market': {'min': '582', 'sec': '2', 'update_time': datetime.datetime(2019, 6, 6, 7, 7, 12, 153219)}, 'candles': {'min': '592', 'sec': '6', 'update_time': datetime.datetime(2019, 6, 6, 7, 7, 12, 197177)}} 468 | - market 관련 요청은 2019년6월6일 7시7분12.153219초 이후 1분동안 582회, 1초동안 2회 호출 가능 469 | - candles 관련 요청은 2019년6월6일 7시7분12.197177초 이후 1분동안 592회, 1초동안 6회 호출 가능 470 | ''' 471 | return self.remaining_req 472 | 473 | ############################################################### 474 | 475 | def _update_remaining_req(self, resp): 476 | if 'Remaining-Req' not in resp.headers.keys(): 477 | return None 478 | keyvals = resp.headers['Remaining-Req'].split('; ') 479 | group = None 480 | keyval = dict() 481 | for _keyval in keyvals: 482 | kv = _keyval.split('=') 483 | if kv[0] == 'group': 484 | group = kv[1] 485 | else: 486 | keyval[kv[0]] = kv[1] 487 | if group is None: 488 | return 489 | keyval['update_time'] = datetime.now() 490 | self.remaining_req[group] = keyval 491 | 492 | 493 | def _get(self, url, headers=None, data=None, params=None): 494 | resp = requests.get(url, headers=headers, data=data, params=params) 495 | if resp.status_code not in [200, 201]: 496 | logging.error('get(%s) failed(%d)' % (url, resp.status_code)) 497 | if resp.text is not None: 498 | logging.error('resp: %s' % resp.text) 499 | raise Exception('request.get() failed(%s)' % resp.text) 500 | raise Exception( 501 | 'request.get() failed(status_code:%d)' % resp.status_code) 502 | self._update_remaining_req(resp) 503 | return json.loads(resp.text) 504 | 505 | def _post(self, url, headers, data): 506 | resp = requests.post(url, headers=headers, data=data) 507 | if resp.status_code not in [200, 201]: 508 | logging.error('post(%s) failed(%d)' % (url, resp.status_code)) 509 | if resp.text is not None: 510 | raise Exception('request.post() failed(%s)' % resp.text) 511 | raise Exception( 512 | 'request.post() failed(status_code:%d)' % resp.status_code) 513 | self._update_remaining_req(resp) 514 | return json.loads(resp.text) 515 | 516 | def _delete(self, url, headers, data): 517 | resp = requests.delete(url, headers=headers, data=data) 518 | if resp.status_code not in [200, 201]: 519 | logging.error('delete(%s) failed(%d)' % (url, resp.status_code)) 520 | if resp.text is not None: 521 | raise Exception('request.delete() failed(%s)' % resp.text) 522 | raise Exception( 523 | 'request.delete() failed(status_code:%d)' % resp.status_code) 524 | self._update_remaining_req(resp) 525 | return json.loads(resp.text) 526 | 527 | def _load_markets(self): 528 | try: 529 | market_all = self.get_market_all() 530 | if market_all is None: 531 | return 532 | markets = [] 533 | for market in market_all: 534 | markets.append(market['market']) 535 | return markets 536 | except Exception as e: 537 | logging.error(e) 538 | raise Exception(e) 539 | 540 | def _get_token(self, query): 541 | payload = { 542 | 'access_key': self.access_key, 543 | 'nonce': int(time.time() * 1000), 544 | } 545 | if query is not None: 546 | payload['query'] = urlencode(query) 547 | return jwt.encode(payload, self.secret, algorithm='HS256').decode('utf-8') 548 | 549 | def _get_headers(self, query=None): 550 | headers = {'Authorization': 'Bearer %s' % self._get_token(query)} 551 | return headers 552 | 553 | def _is_valid_price(self, price): 554 | ''' 555 | 원화 마켓 주문 가격 단위 556 | 원화 마켓은 호가 별 주문 가격의 단위가 다릅니다. 아래 표를 참고하여 해당 단위로 주문하여 주세요. 557 | https://docs.upbit.com/v1.0/docs/%EC%9B%90%ED%99%94-%EB%A7%88%EC%BC%93-%EC%A3%BC%EB%AC%B8-%EA%B0%80%EA%B2%A9-%EB%8B%A8%EC%9C%84 558 | ~10 : 0.01 559 | ~100 : 0.1 560 | ~1,000 : 1 561 | ~10,000 : 5 562 | ~100,000 : 10 563 | ~500,000 : 50 564 | ~1,000,000 : 100 565 | ~2,000,000 : 500 566 | +2,000,000 : 1,000 567 | ''' 568 | if price <= 10: 569 | if (price*100) != int(price*100): 570 | return False 571 | elif price <= 100: 572 | if (price*10) != int(price*10): 573 | return False 574 | elif price <= 1000: 575 | if price != int(price): 576 | return False 577 | elif price <= 10000: 578 | if (price % 5) != 0: 579 | return False 580 | elif price <= 100000: 581 | if (price % 10) != 0: 582 | return False 583 | elif price <= 500000: 584 | if (price % 50) != 0: 585 | return False 586 | elif price <= 1000000: 587 | if (price % 100) != 0: 588 | return False 589 | elif price <= 2000000: 590 | if (price % 500) != 0: 591 | return False 592 | elif (price % 1000) != 0: 593 | return False 594 | return True 595 | --------------------------------------------------------------------------------