해당 글에서 이어지는 내용입니다.
def execute_trade_logic(df):
global balance
current_close = df['c'].iloc[-1]
lower_band = df['bb_Lower'].iloc[-1]
upper_band = df['bb_Upper'].iloc[-1]
current_rsi = df['RSI'].iloc[-1]
MA20 = df['MA20'].iloc[-1]
MA5 = df['MA5'].iloc[-1]
long_amt = balance[target_symbol]['LONG']['amt']
long_ent = balance[target_symbol]['LONG']['ent']
short_amt = balance[target_symbol]['SHORT']['amt']
short_ent = balance[target_symbol]['SHORT']['ent']
lev = balance[target_symbol]['leverage']
long_positon_margin = long_amt * long_ent
# 롱 포지션 진입 조건 체크
if long_positon_margin + current_close * order_unit_amount > balance['total'] * lev :
print('주문 가능 금액 부족')
elif current_close < lower_band and current_rsi <= 30:
apg = 1 - price_gap_entry * (1 + 0.5 * (long_amt / order_unit_amount - 1)) / 100
print('apg :', apg)
if long_amt > 0 and current_close >= long_ent * apg:
print(f'평단가 - {price_gap_entry}% 보다는 아직 높음')
else :
print(f"롱 포지션 진입중... 현재가 : {current_close}, 볼린저 하단 : {lower_band}, RSI : {current_rsi}")
LIMIT_order(target_symbol, 'buy', 'LONG', order_unit_amount, current_close, 1)
# 롱 포지션 정리 조건 체크
if current_close >= upper_band : # and current_rsi >= 70
if long_amt > order_unit_amount * 2:
print("포지션 일부 매도중...")
LIMIT_order(target_symbol, 'sell', 'LONG', order_unit_amount, current_close, 1)
elif 0 < long_amt <= order_unit_amount * 2:
print("포지션 전체 매도중...")
LIMIT_order(target_symbol, 'sell', 'LONG', long_amt, current_close, 1)
short_positon_margin = short_amt * short_ent
# 숏 포지션 진입 조건 체크
if short_positon_margin + current_close * order_unit_amount > balance['total'] * lev :
print('주문 가능 금액 부족')
elif current_close > upper_band and current_rsi >= 70 and long_amt == 0 and current_close >= MA5 * (1 + price_gap_entry / 100):
apg = 1 + price_gap_entry * (1 + 0.5 * (short_amt / order_unit_amount - 1)) / 100
print('apg :', apg)
if short_amt > 0 and current_close <= short_ent * apg:
print(f'평단가 + {price_gap_entry}% 보다는 아직 낮음')
else :
print(f"숏 포지션 진입중... 현재가 : {current_close}, 볼린저 하단 : {upper_band}, RSI : {current_rsi}")
LIMIT_order(target_symbol, 'sell', 'SHORT', order_unit_amount, current_close, 1)
위의 함수에서 대부분의 매수, 매도 조건을 관리합니다.
if long_positon_margin + current_close * order_unit_amount > balance['total'] * lev :
해당 조건문은 현재 보유중인 포지션의 금액 + 새로 주문하려는 금액이
잔고에 남은 돈을 초과할 경우에 주문을 넣지 않도록 제한하기 위한 코드입니다.
레버리지 배율에 따른 증거금 청산 금액 등이 고려되지 않은 단순 계산이므로
고배율 매매의 경우엔 제대로 작동하지 않을 수 있습니다.
저는 고배율 레버리지를 권장하지 않으므로 해당 코드의 검토는 나중에 하겠습니다.
크게 중요치 않은 부분이니 그냥 넘어가셔도 됩니다.
1. RSI 사용하지 않기
만약 볼밴만 필요하고, RSI를 빼고 싶다면 본문 22번째 줄에서
elif current_close < lower_band and current_rsi <= 30:
↓
elif current_close < lower_band :
이렇게 RSI에 관한 부분을 지우시면 됩니다.
RSI가 더 낮을때를 조건으로 하려면 20과 같은 숫자로 바꾸시면 됩니다.
2. 첫 매수 구간을 이동평균으로 변경
long_positon_margin = long_amt * long_ent
# 롱 포지션 진입 조건 체크
if long_positon_margin + current_close * order_unit_amount > balance['total'] * lev :
print('주문 가능 금액 부족')
elif current_close < lower_band and current_rsi <= 30:
apg = 1 - price_gap_entry * (1 + 0.5 * (long_amt / order_unit_amount - 1)) / 100
...생략
만약 롱포지션이 비어있을 때,
종가가 20분 이평보다 낮을 때,
0.01개는 보유하고 싶다면
위의 코드에서 다음과 같이 추가하시면 됩니다.
long_positon_margin = long_amt * long_ent
# 롱 포지션 진입 조건 체크
if long_positon_margin + current_close * order_unit_amount > balance['total'] * lev :
print('주문 가능 금액 부족')
elif long_amt == 0 and current_close <= MA20 :
print(f"롱 포지션 진입중... 현재가 : {current_close}, 20이동평균 : {MA20}")
LIMIT_order(target_symbol, 'buy', 'LONG', order_unit_amount, current_close, 1)
elif current_close < lower_band and current_rsi <= 30:
apg = 1 - price_gap_entry * (1 + 0.5 * (long_amt / order_unit_amount - 1)) / 100
...생략
직관적인 코드라서 어렵지 않으실겁니다.
long_amt = 보유중인 수량
and # 그리고
current_close = 종가
MA20 = 20분 이평
보기 쉽게 정리하면
# 보유중인 롱 포지션 수량이 0
if long_amt == 0 :
# 종가가 20분 이평보다 작거나 같을 때
if current_close <= MA20 :
# 위의 둘을 합치면
if long_amt == 0 and current_close <= MA20 :
3. 보유한 물량이 많으면 이동평균에서 일부 매도
이번엔 보유한 수량이 0.03개보다 많고
종가가 20분 이동평균 보다 높았다면
0.03개만 남기고 전부 매도
# 롱 포지션 정리 조건 체크
if current_close >= order_unit_amount : # and current_rsi >= 70
if long_amt > order_unit_amount * 2:
print("포지션 일부 매도중...")
LIMIT_order(target_symbol, 'sell', 'LONG', order_unit_amount, current_close, 1)
elif 0 < long_amt <= order_unit_amount * 2:
print("포지션 전체 매도중...")
LIMIT_order(target_symbol, 'sell', 'LONG', long_amt, current_close, 1)
# 아래가 추가된 내용
elif long_amt > order_unit_amount * 3 and current_close >= MA20 :
print("포지션 일부 매도중...")
LIMIT_order(target_symbol, 'sell', 'LONG', long_amt - order_unit_amount * 3, current_close, 1)
위의 마지막 elif의 내용을 추가하시면 됩니다.
long_amt = 보유중인 수량
order_unit_amount = 최소 주문 단위. (여기에 * 3)
and # 그리고
current_close = 종가
MA20 = 20분 이동평균
4. 숏 포지션을 MA5 -> MA20에 정리로 변경
이번에는 보유중인 숏 포지션을 MA5에 정리하는 것이 아니라
MA20보다 낮을 때 정리하도록 변경한다면, 아래의 함수에서
def update_chart(df, data):
# 숏 포지션 정리 조건 체크
if balance[target_symbol]['SHORT']['amt'] > 0 and df['c'].iloc[-1] <= df['MA5'].iloc[-1]: # and current_rsi >= 70
print("포지션 전체 매도중...")
LIMIT_order(target_symbol, 'buy', 'SHORT', balance[target_symbol]['SHORT']['amt'], df['c'].iloc[-1], 1)
위의 조건에서 df['MA5'].iloc[-1] 이 MA5 입니다.
이것을 df['MA20'].iloc[-1] 으로 변경하시면 됩니다.
해당 글에서 추가된 조건문들은 테스트 해보진 않았지만
아마 정상적으로 작동할거라 생각됩니다.
5. 잡담
이런식으로 조건문들을 조금 바꿔주기만 해도 여러 전략이 가능합니다.
예를들어 비트가 앞으로 계속 상승할 것은 같은데
풀매수하기는 겁나고 적당히 낮은 가격에 일정 수량만 매수하고 싶다면
가격이 볼밴 상단을 넘어가도 매도하지 않도록 바꾼다거나
매수, 매도 매매 방식을 아예 똑같이 만들어서 평균회귀 전략을 쓰거나
반대로 상승, 하락 돌파가 나올 때 추격을 하도록 만들 수도 있습니다.
막상 해보면 전체 코드를 작성하는건 좀 어려울 수 있는데
이미 만들어진 코드에서 일부 기능만 수정하는 것은 생각보다 쉽습니다.
전략을 구상하실 때 항상 과거 차트들도 분석하면서
최대한 리스크에 대응할 수 있도록
적당한 익절, 손절 기준도 만드는 것이 좋습니다.
'파이썬 > 바이낸스 선물 자동매매' 카테고리의 다른 글
[자동매매] 볼린저 밴드 + RSI (0) | 2024.12.06 |
---|