def main(): args = parse_arguments() exchange = ExchangeConnection(args=args) # Store and print the "hello" message received from the exchange. This # contains useful information about your positions. Normally you start with # all positions at zero, but if you reconnect during a round, you might # have already bought/sold symbols and have non-zero positions. hello_message = exchange.read_message() print("First message from exchange:", hello_message) # Send an order for BOND at a good price, but it is low enough that it is # unlikely it will be traded against. Maybe there is a better price to # pick? Also, you will need to send more orders over time. # --- BOND 마켓 메이킹 설정 --- FAIR_VALUE = 1000 # BOND fair value (고정) ORDER_SIZE = 100 # 한 번에 최대한 많이 (포지션 한도 = 100) MAX_POSITION = 100 # 최대 포지션 한도 REFRESH_INTERVAL = 5.0 # 주문 갱신 주기 (초) position = 0 # 현재 BOND 포지션 order_id = 0 # 단조 증가하는 주문 ID active_orders = {} # {order_id: {"dir": ..., "price": ...}} market_open = False # 시장 open 여부 (open 전에는 주문 불가) def next_id(): nonlocal order_id order_id += 1 return order_id def cancel_all_bond_orders(): """BOND 주문 전부 한 번에 취소 (mass_cancel 사용)""" exchange.send_mass_cancel_message(symbol="BOND") active_orders.clear() def place_bond_orders(): """포지션 한도 안에서 bid/ask 양방향 주문""" if not market_open: return cancel_all_bond_orders() # 포지션이 음수면 매수 가격을 올려서 빨리 사들임 # 포지션이 양수면 매도 가격을 내려서 빨리 팖 skew = position // 10 # 포지션 10마다 1틱 조정 buy_price = min(FAIR_VALUE - 1 + skew, FAIR_VALUE - 1) # 최대 999 sell_price = max(FAIR_VALUE + 1 + skew, FAIR_VALUE + 1) # 최소 1001 buy_size = min(ORDER_SIZE, MAX_POSITION - position) sell_size = min(ORDER_SIZE, MAX_POSITION + position) if buy_size > 0: bid = next_id() exchange.send_add_message( order_id=bid, symbol="BOND", dir=Dir.BUY, price=buy_price, size=buy_size ) active_orders[bid] = {"dir": Dir.BUY, "price": buy_price} if sell_size > 0: ask = next_id() exchange.send_add_message( order_id=ask, symbol="BOND", dir=Dir.SELL, price=sell_price, size=sell_size ) active_orders[ask] = {"dir": Dir.SELL, "price": sell_price} print(f" BOND 주문 → 매수: {buy_price} x{buy_size}, 매도: {sell_price} x{sell_size}, 포지션: {position}") # Set up some variables to track the bid and ask price of a symbol. Right # now this doesn't track much information, but it's enough to get a sense # of the VALE market. vale_bid_price, vale_ask_price = None, None vale_last_print_time = time.time() last_refresh = time.time() # Here is the main loop of the program. It will continue to read and # process messages in a loop until a "close" message is received. You # should write to code handle more types of messages (and not just print # the message). Feel free to modify any of the starter code below. # # Note: a common mistake people make is to call write_message() at least # once for every read_message() response. # # Every message sent to the exchange generates at least one response # message. Sending a message in response to every exchange message will # cause a feedback loop where your bot's messages will quickly be # rate-limited and ignored. Please, don't do that! while True: message = exchange.read_message() # Some of the message types below happen infrequently and contain # important information to help you understand what your bot is doing, # so they are printed in full. We recommend not always printing every # message because it can be a lot of information to read. Instead, let # your code handle the messages and just print the information # important for you! if message["type"] == "close": print("The round has ended") break elif message["type"] == "open": # 시장이 열렸을 때 주문 시작 (open 전에 주문하면 reject됨) print("Market opened:", message) market_open = True place_bond_orders() elif message["type"] == "error": print(message) elif message["type"] == "reject": print(message) # 거부된 주문은 active_orders에서 제거 oid = message.get("order_id") active_orders.pop(oid, None) elif message["type"] == "fill": print(message) # 체결 시 포지션 업데이트 후 주문 재보충 qty = message["size"] if message["dir"] == Dir.BUY: position += qty else: position -= qty place_bond_orders() elif message["type"] == "book": if message["symbol"] == "VALE": def best_price(side): if message[side]: return message[side][0][0] vale_bid_price = best_price("buy") vale_ask_price = best_price("sell") now = time.time() if now > vale_last_print_time + 1: vale_last_print_time = now print( { "vale_bid_price": vale_bid_price, "vale_ask_price": vale_ask_price, } ) # 주기적으로 BOND 주문 갱신 (주문 만료 방지) now = time.time() if now - last_refresh > REFRESH_INTERVAL: last_refresh = now place_bond_orders()