Limetime's TimeLine
article thumbnail
반응형

 최근 SNL 코리아에서 주현영 기자가 이준석 당내 대표를 취재하는 장면이 있었는데 이준석은 코인 자동매매를 돌리고 있다고 했다. 그것도 대선 3~4번 나갈 금액을 수익화했다고 전했다. 

출처 : 유튜브. 쿠팡플레이 Coupang Play

 그 말을 듣고 나는 갑자기 궁금해졌다. 구글링 해서 제일 쉬운 자동매매 프로그램을 만들어보았다.

 우선 세계 3대 비트코인 선물 거래소인 Bybit을 이용해서 프로그램을 짤 것이기 때문에 Bybit에서 제공하는 API를 만들자! 가입은 필수다!

 

Bybit API 만들기!

 로그인을 하고 계정 모양을 누르면 API링크로 들어갈 수 있다.

 그리고 Create New Key를 눌러 Key를 만들어주자!

 

 위와 같은 화면이 나오는데 이제부터는 하나씩 자세히 알아보자.

<API Key Usage>
  API Transaction : 직접 사용할 것이기 때문에 이것을 사용할 것이다.
  Connect to Third-Party Applications : 다른 프로그램에서 연결해서 사용할 때 사용.
  Name : 별칭 같은건데 아무거나 입력해주면 된다.
<API Key permissions (check all that apply)>
  Read-Write : RW속성, 읽고 쓰기 둘 다 하겠다. 이것을 써야 사고 팔 수 있다.
  Read-Only : 읽기만 하겠다. 그냥 정보만 들고 오겠다.
  Contract : 선물 사고 파는 것에 관여 (Position, 주문)
  SPOT : 현물 사고 파는 것에 관여 (주문)
  Wallet : 지갑 관리 (출금, 계정 내 이동, 코인 환전)
<IP Access to API Keys>
  All IPs : 모든 IP에 대해 접근 시킨다. (단, 3개월 뒤 이 Key는 소멸된다.)
  Specified IPs only : 특정 IP로만 접근시킨다. (보안에 강함)

 빨간색 표시를 해놓은 부분은 선택한 부분이다.

 API key permissions 부분은 다 체크를 해주긴 했다. 하지만 당장은 SPOT(현물) 주문과 Wallet(지갑) 관리는 안할거라서 체크를 하지 않아도 무방하다.

 그 후 IP Access to API Keys 부분의 Specified IPs only에 프로그램을 돌릴 IP주소를 입력해준다.

 (CMD 했을 때 IP말고 공인 IP를 적어줘야 하는데 https://myip.com 에 접속하면 볼 수 있다.)

 

 다했으면 Submit을 눌러서 제출하자! 그러면 API Key와 API Secret을 얻을 수 있다.

 여기서 주의! API Key와 API Secret을 반드시 복사해두자!

 

 IP Addr 옆의 연필을 누르면 IP주소를 수정할 수 있다. API ID는 볼 수 있는 반면 Secret은 볼 수 없다.

 그러니 API Secret을 반드시 복사해두자!

 


 

 

BYBIT GoldenCross/DeadCross 자동 매매의 위험 검증.

이전 글에서 Bybit API를 이용한 골든크로스/데드크로스 자동매매 프로그램을 구현했는데 그 프로그램에 대한 위험성 검증을 했다. Bybit API를 이용한 골드/데드 크로스 자동매매 프로그램.  최근 S

limetimeline.tistory.com

import pandas as pd
import datetime
import requests
import time
import calendar
from pybit import HTTP
from datetime import datetime, timedelta, timezone

from requests.api import post

apiKey = 'Input your API KEY'
apiSecret = 'Input your API Secret'
#symbol to be traded
symbol = 'MANAUSDT'

query_kilne = 'https://api.bybit.com/public/linear/kline?symbol=' # USDT
# query_kilne = 'https://api.bybit.com/v2/public/kline/list?symbol=' # USD
latest_infoSymbol = 'https://api.bybit.com/v2/public/tickers?symbol='

#candle in minutes
tick_interval  = '1'

#quantity to be traded in USD
qty1 = 3

opt=0
while True:
    bybitticker=symbol

    now = datetime.utcnow()
    unixtime = calendar.timegm(now.utctimetuple())
    since = unixtime

    start=str(since-60*60*int(tick_interval))
    url = query_kilne+bybitticker+'&interval='+tick_interval+'&from='+str(start)
    data = requests.get(url).json()
    D = pd.DataFrame(data['result'])

    marketprice = latest_infoSymbol + symbol
    res = requests.get(marketprice)
    data = res.json()
    lastprice = float(data['result'][0]['last_price'])

    price = lastprice
    df = D['close']

    ma9 = df.rolling(window=9).mean()
    ma26 = df.rolling(window=26).mean()

    test1=ma9.iloc[-2]-ma26.iloc[-2]
    test2=ma9.iloc[-1]-ma26.iloc[-1]

    session = HTTP(
        endpoint = 'https://api.bybit.com/',
        api_key=apiKey,
        api_secret = apiSecret)

    positionsize=session.my_position(symbol=symbol)['result'][0]['size']
    if session.my_position(symbol=symbol)['result'][0]['side']=='Sell':
        positionsize=positionsize*-1
        
        lastprice = float(session.latest_information_for_symbol(symbol=symbol)['result'][0]['last_price'])
    call='None'
    try:
        if test1>0 and test2<0:
            if positionsize>0:
                print('skip')
                time.sleep(2)
                continue
            call = 'Dead Cross'
            qty = qty1
            if positionsize<0:
                qty=qty1+abs(positionsize)

            if opt == 0:
                opt = 1

                print(session.place_active_order(
                    symbol=bybitticker,
                    side='Buy',
                    order_type='Market',
                    qty=qty1,
                    time_in_force="GoodTillCancel",
                    reduce_only=False,
                    close_on_trigger=False
                ))

                print(session.place_active_order(
                    symbol=bybitticker,
                    side='Buy',
                    order_type='Market',
                    qty=qty1,
                    time_in_force="GoodTillCancel",
                    reduce_only=True,
                    close_on_trigger=False
                ))

        if test1<0 and test2>0:
            if positionsize<0:
                print('skip')
                time.sleep(2)
                continue
            call='Golden Cross'
            qty=qty1

             if positionsize>0:
                qty=qty1+abs(positionsize)
            if opt == 1:
                opt = 0
                print(session.place_active_order(
                        symbol=bybitticker,
                        side='Sell',
                        order_type='Market',
                        qty=qty1,
                        time_in_force="GoodTillCancel",
                        reduce_only=True,
                        close_on_trigger=False
                    ))

                print(session.place_active_order(
                        symbol=bybitticker,
                        side='Sell',
                        order_type='Market',
                        qty=qty1,
                        time_in_force="GoodTillCancel",
                        reduce_only=False,
                        close_on_trigger=False
                    ))


    except:
        pass

    print('Name: ', bybitticker)
    print('Date: ', now)
    print('price: ', lastprice)
    print('MA 9: ', round(ma9.iloc[-1],2))
    print('MA 26: ', round(ma26.iloc[-1],2))
    print('Golden Cross/Dead Cross: ', call)
    print('opt: ', opt)
    print('')

    time.sleep(2)

 

 위의 코드를 간략히 설명하자면...

 목표 코인은 MANAUSDT (MANA, 디센트럴랜드)이고 한 번 주문할 때 마다 3개씩 시장가로 구매하도록 되어 있다.

 첫 시도에서 Dead Cross일 때 Long 포지션을 주문하고 Golden Cross일 때 Long 포지션을 청산하고 Short 포지션을 주문한다. 그 후 Dead Cross가 왔을 때 Long 포지션을 주문하고 Short 포지션을 청산한다. (반복)

<Golden Cross / Dead Cross with MA 9, 26>


Golden CrossMA(이동평균선) 9가 MA 26을 치고 올라갈 때를 말한다.
Dead Cross는 MA(이동평균선) 26이 MA 9를 치고 올라갈 때를 말한다.

 

 처음에 나는 Golden Cross 이후로 오르고 Dead Cross 때 내려간다고 생각했는데 이게 정확하게 따라가지 않았다. 내가 무지했기 때문이기도 하지만 예측불가인 것이 당연했다. 코인은 더 위험하다.

 이번 코드는 Golden Cross일 때, Dead Cross일 때의 두 조건에만 반응하는 프로그램이라 고쳐야할 부분은 크게 많지 않다. 가져다 쓸 경우 저 코드 그대로 쓰지 말고 적당히 고쳐서 쓰길 바란다. 저 코드는 완벽한 지표가 될 수 없다.

 

apiKey = 'Input your API KEY'   # API Key를 입력하자!
apiSecret = 'Input your API Secret'   # API Secret을 입력하자!
#symbol to be traded
symbol = 'MANAUSDT'   # 가지고 놀 코인이름을 입력하자!

query_kilne = 'https://api.bybit.com/public/linear/kline?symbol=' # USDT   # 코인 선물에서 USDT를 다룰 때 사용하는 API
# query_kilne = 'https://api.bybit.com/v2/public/kline/list?symbol=' # USD   # 코인 선물에서 USD를 다룰 때 사용하는 API

#candle in minutes
tick_interval  = '1'   # 몇 분 차트로 볼지 설정. 1은 1분 차트.
<코인선물 USD와 USDT로 거래하는 API가 서로 다르다! 반드시 알맞게 고쳐야한다.>
USD : BTCUSD나 MANAUSD 즉, USD로 거래하고 싶다.
   => symbol = 'BTCUSD' 또는 'MANAUSD'
   => query_kilne = 'https://api.bybit.com/v2/public/kline/list?symbol='

USDT : BTCUSDT나 MANAUSDT 즉, USDT로 거래하고 싶다.
   => symbol = 'BTCUSDT' 또는 'MANAUSDT'
   => query_kilne = 'https://api.bybit.com/public/linear/kline?symbol=' 

 

#quantity to be traded in USDT or USD
qty1 = 3   # 한 번 거래할 때 마다 양. 코인마다 다르겠지?

 

# MA(이동평균선) 9와 MA 26을 계산하는 작업.
ma9 = df.rolling(window=9).mean()
ma26 = df.rolling(window=26).mean()

call = 'Dead Cross'   # 데드크로스가 감지 되었을 때 여기로 들어와서 콘솔에 Dead Cross 출력

call = 'Golden Cross'   # 골든크로스가 감지 되었을 때 여기로 들어와서 콘솔에 Golden Cross 출력

 

 print(session.place_active_order(   # 주문하기.
                    symbol=bybitticker,   # 주문할 코인
                    side='Buy',   # Long주문
                    order_type='Market',   # 시장가.
                    qty=qty1,   # 개수
                    time_in_force="GoodTillCancel",
                    reduce_only=False,
                    close_on_trigger=False
                ))

print(session.place_active_order(   # 주문하기.
                    symbol=bybitticker,   # 주문할 코인
                    side='Sell',   # Long청산
                    order_type='Market',   # 시장가.
                    qty=qty1,   # 개수
                    time_in_force="GoodTillCancel",
                    reduce_only=True,
                    close_on_trigger=False
                ))

print(session.place_active_order(   # 주문하기.
                    symbol=bybitticker,   # 주문할 코인
                    side='Sell',   # Short주문
                    order_type='Market',   # 시장가.
                    qty=qty1,   # 개수
                    time_in_force="GoodTillCancel",
                    reduce_only=False,
                    close_on_trigger=False
                ))

print(session.place_active_order(   # 주문하기.
                    symbol=bybitticker,   # 주문할 코인
                    side='Buy',   # Short주문
                    order_type='Market',   # 시장가.
                    qty=qty1,   # 개수
                    time_in_force="GoodTillCancel",
                    reduce_only=True,
                    close_on_trigger=False
                ))
여기서 주의해야할 것은 주문할 때는 Buy(Long), Sell(Short) 그대로 적지만
청산할 경우 반드시 반대로 Buy(Short청산), Sell(Long청산)로 적어주고 reduce_only를 True로 해주어야 한다.

 

추가로 지정가 매매의 경우 아래와 같이 해주면 된다.
order_type과 price만 추가해주면 된다.
나머지는 위와 같다.
print(session.place_active_order(
    symbol=bybitticker,
    side='포지션',
    qty=qty1, 
    order_type='Limit',   # 지정가
    price=lastprice,   # 가격인데 원하는 가격을 줘도되고 lastprice는 현재가격을 담고 있다.
    time_in_force="GoodTillCancel",
    reduce_only=False,
    close_on_trigger=False
))

 

 수정할 것은 이 정도? 만 하면 될 것 같다.

 더 많은 API를 제공하고 있으니 더 자세한 API 정보는 https://bybit-exchange.github.io/docs/linear/#t-introduction 여기로 들어가보면 된다.

 

Bybit API Docs

 

bybit-exchange.github.io

궁금한 사항이 있다면 댓글을 남겨주십시오!

 

 혹시나 코인 선물이나 위클리 옵션에 관심이 있다면 '안쌤TV'로 와서 함께 공부하는 것도 좋을 것 같다.

 요즘 내가 도와드리고 있는 선생님이신데 내공이 상당하시다. 궁금한 것도 질문하면 잘 알려 주신다.

 요즘 Youtube 방송도 저녁 10시부터 코인선물 방송을 하시고 오픈채팅도 운영하고 있으니 참고!

 

위클리옵션.국내선물/비트코인 - 안쌤... : 네이버 카페

주식/해외선물(홍콩항셍,나스닥,오일)/비트코인 등 실전 매매 전략과 철학을 배울 수 있는 공간입니다.

cafe.naver.com

 

반응형
profile

Limetime's TimeLine

@Limetime

포스팅이 좋았다면 "공감❤️" 또는 "구독👍🏻" 해주세요!