first commit
This commit is contained in:
132
services/order_service.go
Normal file
132
services/order_service.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// OrderService 주식 주문 서비스 (매수/매도/정정/취소)
|
||||
type OrderService struct {
|
||||
client *KiwoomClient
|
||||
}
|
||||
|
||||
var orderService *OrderService
|
||||
|
||||
// GetOrderService 주문 서비스 싱글턴 반환
|
||||
func GetOrderService() *OrderService {
|
||||
if orderService == nil {
|
||||
orderService = &OrderService{client: GetKiwoomClient()}
|
||||
}
|
||||
return orderService
|
||||
}
|
||||
|
||||
// OrderRequest 주문 요청 파라미터
|
||||
type OrderRequest struct {
|
||||
Exchange string // KRX, NXT, SOR
|
||||
Code string // 종목코드
|
||||
Qty string // 주문수량
|
||||
Price string // 주문단가 (시장가 시 빈 문자열)
|
||||
TradeTP string // 0:보통, 3:시장가, 5:조건부지정가, 6:최유리, 7:최우선
|
||||
}
|
||||
|
||||
// OrderResult 주문 응답
|
||||
type OrderResult struct {
|
||||
OrderNo string `json:"orderNo"`
|
||||
ReturnCode int `json:"returnCode"`
|
||||
ReturnMsg string `json:"returnMsg"`
|
||||
}
|
||||
|
||||
// Buy 매수주문 (kt10000)
|
||||
func (s *OrderService) Buy(req OrderRequest) (*OrderResult, error) {
|
||||
body := map[string]string{
|
||||
"dmst_stex_tp": req.Exchange,
|
||||
"stk_cd": req.Code,
|
||||
"ord_qty": req.Qty,
|
||||
"ord_uv": req.Price,
|
||||
"trde_tp": req.TradeTP,
|
||||
"cond_uv": "",
|
||||
}
|
||||
|
||||
respBody, err := s.client.post("kt10000", "/api/dostk/ordr", body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("매수주문 실패: %w", err)
|
||||
}
|
||||
|
||||
return parseOrderResult(respBody)
|
||||
}
|
||||
|
||||
// Sell 매도주문 (kt10001)
|
||||
func (s *OrderService) Sell(req OrderRequest) (*OrderResult, error) {
|
||||
body := map[string]string{
|
||||
"dmst_stex_tp": req.Exchange,
|
||||
"stk_cd": req.Code,
|
||||
"ord_qty": req.Qty,
|
||||
"ord_uv": req.Price,
|
||||
"trde_tp": req.TradeTP,
|
||||
"cond_uv": "",
|
||||
}
|
||||
|
||||
respBody, err := s.client.post("kt10001", "/api/dostk/ordr", body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("매도주문 실패: %w", err)
|
||||
}
|
||||
|
||||
return parseOrderResult(respBody)
|
||||
}
|
||||
|
||||
// Modify 정정주문 (kt10002)
|
||||
func (s *OrderService) Modify(exchange, origOrdNo, code, qty, price string) (*OrderResult, error) {
|
||||
body := map[string]string{
|
||||
"dmst_stex_tp": exchange,
|
||||
"orig_ord_no": origOrdNo,
|
||||
"stk_cd": code,
|
||||
"mdfy_qty": qty,
|
||||
"mdfy_uv": price,
|
||||
"mdfy_cond_uv": "",
|
||||
}
|
||||
|
||||
respBody, err := s.client.post("kt10002", "/api/dostk/ordr", body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("정정주문 실패: %w", err)
|
||||
}
|
||||
|
||||
return parseOrderResult(respBody)
|
||||
}
|
||||
|
||||
// Cancel 취소주문 (kt10003)
|
||||
// qty: "0" = 전량취소
|
||||
func (s *OrderService) Cancel(exchange, origOrdNo, code, qty string) (*OrderResult, error) {
|
||||
body := map[string]string{
|
||||
"dmst_stex_tp": exchange,
|
||||
"orig_ord_no": origOrdNo,
|
||||
"stk_cd": code,
|
||||
"cncl_qty": qty,
|
||||
}
|
||||
|
||||
respBody, err := s.client.post("kt10003", "/api/dostk/ordr", body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("취소주문 실패: %w", err)
|
||||
}
|
||||
|
||||
return parseOrderResult(respBody)
|
||||
}
|
||||
|
||||
// parseOrderResult 주문 응답 JSON 파싱 공통 함수
|
||||
func parseOrderResult(body []byte) (*OrderResult, error) {
|
||||
var result struct {
|
||||
OrdNo string `json:"ord_no"`
|
||||
ReturnCode int `json:"return_code"`
|
||||
ReturnMsg string `json:"return_msg"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &result); err != nil {
|
||||
return nil, fmt.Errorf("주문 응답 파싱 실패: %w", err)
|
||||
}
|
||||
if result.ReturnCode != 0 {
|
||||
return nil, fmt.Errorf("주문 오류: %s", result.ReturnMsg)
|
||||
}
|
||||
return &OrderResult{
|
||||
OrderNo: result.OrdNo,
|
||||
ReturnCode: result.ReturnCode,
|
||||
ReturnMsg: result.ReturnMsg,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user