420 lines
20 KiB
C++
420 lines
20 KiB
C++
// CPRobotDlg.cpp : 구현 파일
|
||
//
|
||
|
||
#include "stdafx.h"
|
||
#include "CPRobot.h"
|
||
#include "CPRobotDlg.h"
|
||
#include <WinUser.h>
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#endif
|
||
|
||
|
||
ICpTdUtilPtr g_pTdUtil = NULL;
|
||
|
||
|
||
CCPRobotDlg::CCPRobotDlg(CWnd* pParent /*=NULL*/)
|
||
: CDialog(CCPRobotDlg::IDD, pParent)
|
||
, m_iAmountSet(0)
|
||
, m_fMinPriceSet(0.0f)
|
||
, m_fMaxPriceSet(0.0f)
|
||
, m_iSellTick(0)
|
||
, m_iLossCutTick(0)
|
||
, m_iTrailingTick(0)
|
||
, m_iCancelDelay(0)
|
||
, m_bPutOption(FALSE)
|
||
{
|
||
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
||
|
||
m_iBalance = 0;
|
||
m_pOpJpBid = NULL;
|
||
}
|
||
|
||
void CCPRobotDlg::DoDataExchange(CDataExchange* pDX)
|
||
{
|
||
CDialog::DoDataExchange(pDX);
|
||
DDX_Control(pDX, IDC_LIST_ITEMS, m_ResultList);
|
||
DDX_Text(pDX, IDC_EDIT_ORDERINGPRICE, m_iAmountSet);
|
||
DDX_Text(pDX, IDC_EDIT_ORDERING_TICK_MIN, m_fMinPriceSet);
|
||
DDX_Text(pDX, IDC_EDIT_ORDERING_TICK_MAX, m_fMaxPriceSet);
|
||
DDX_Text(pDX, IDC_EDIT_SELL_TICK, m_iSellTick);
|
||
DDX_Text(pDX, IDC_EDIT_LOSS_CUT_TICK, m_iLossCutTick);
|
||
DDX_Text(pDX, IDC_EDIT_TRAING_TICK, m_iTrailingTick);
|
||
DDX_Text(pDX, IDC_EDIT_CANCEL_DELAY, m_iCancelDelay);
|
||
DDX_Radio(pDX, IDC_RADIO_CALLOP, m_bPutOption);
|
||
}
|
||
|
||
BEGIN_MESSAGE_MAP(CCPRobotDlg, CDialog)
|
||
ON_WM_PAINT()
|
||
ON_WM_QUERYDRAGICON()
|
||
//}}AFX_MSG_MAP
|
||
ON_BN_CLICKED(IDC_BUTTON_REFRESH_BALANCE, &CCPRobotDlg::OnBnClickedButtonRefreshBalance)
|
||
ON_WM_CREATE()
|
||
ON_WM_DESTROY()
|
||
ON_BN_CLICKED(IDC_BUTTON_START_DEAL, &CCPRobotDlg::OnBnClickedButtonStartDeal)
|
||
ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CCPRobotDlg::OnBnClickedButtonSearch)
|
||
ON_BN_CLICKED(IDC_RADIO_BID, &CCPRobotDlg::OnBnClickedRadioBid)
|
||
ON_BN_CLICKED(IDC_RADIO_ASK, &CCPRobotDlg::OnBnClickedRadioAsk)
|
||
ON_WM_PARENTNOTIFY()
|
||
END_MESSAGE_MAP()
|
||
|
||
|
||
// CCPRobotDlg 메시지 처리기
|
||
BOOL CCPRobotDlg::OnInitDialog()
|
||
{
|
||
CDialog::OnInitDialog();
|
||
|
||
// 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
|
||
// 프레임워크가 이 작업을 자동으로 수행합니다.
|
||
SetIcon(m_hIcon, TRUE); // 큰 아이콘을 설정합니다.
|
||
SetIcon(m_hIcon, FALSE); // 작은 아이콘을 설정합니다.
|
||
|
||
// TODO: 여기에 추가 초기화 작업을 추가합니다.
|
||
|
||
return TRUE; // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
|
||
}
|
||
|
||
int CCPRobotDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
||
{
|
||
if (CDialog::OnCreate(lpCreateStruct) == -1)
|
||
return -1;
|
||
|
||
// TODO: Add your specialized creation code here
|
||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||
|
||
// 모의투자 mjjo53
|
||
// 계좌번호 335190813
|
||
g_pTdUtil.CreateInstance(CLSID_CpTdUtil);
|
||
const short iInitResult = g_pTdUtil->TradeInit(0);
|
||
switch(iInitResult)
|
||
{
|
||
case -1:
|
||
MessageBox("TradeInit 오류");
|
||
return -2;
|
||
break;
|
||
|
||
case 1:
|
||
MessageBox("업무 키 잘못 입력됨");
|
||
return -2;
|
||
break;
|
||
|
||
case 2:
|
||
MessageBox("계좌 비밀번호 잘못 입력됨");
|
||
return -2;
|
||
break;
|
||
|
||
case 3:
|
||
MessageBox("취소됨");
|
||
return -2;
|
||
break;
|
||
}
|
||
|
||
|
||
m_AccountNum = "117126165"; //
|
||
m_AccountNum = "412120700"; //
|
||
m_AccountNum = "335190813"; // mjjo53 모의투자 계좌
|
||
|
||
|
||
m_pOpJpBid.CreateInstance(CLSID_OptionJpBid);
|
||
|
||
m_EventHandler.DispEventAdvise(m_pOpJpBid);
|
||
m_EventHandler.SetIEventHandler(this);
|
||
|
||
ICpOptionCodePtr pOpCode;
|
||
pOpCode.CreateInstance(CLSID_CpOptionCode);
|
||
short iCodeCnt = pOpCode->GetCount();
|
||
|
||
string Code;
|
||
|
||
for(int i=0; i<iCodeCnt; i++)
|
||
{
|
||
Code = (_bstr_t)pOpCode->GetData(0, i);
|
||
m_OpCodeList.push_back(Code);
|
||
}
|
||
pOpCode.Release();
|
||
|
||
return 0;
|
||
}
|
||
|
||
void CCPRobotDlg::OnDestroy()
|
||
{
|
||
CDialog::OnDestroy();
|
||
|
||
// TODO: Add your message handler code here
|
||
m_pOpJpBid.Release();
|
||
|
||
m_EventHandler.DispEventUnadvise(m_pOpJpBid);
|
||
|
||
UpdateData();
|
||
SaveToFile();
|
||
}
|
||
|
||
BOOL CCPRobotDlg::DestroyWindow()
|
||
{
|
||
// TODO: Add your specialized code here and/or call the base class
|
||
g_pTdUtil.Release();
|
||
|
||
return CDialog::DestroyWindow();
|
||
}
|
||
|
||
void CCPRobotDlg::SaveToFile(void)
|
||
{
|
||
FILE* fp = NULL;
|
||
const int iError = fopen_s(&fp, "setting.ini", "wt");
|
||
if(iError != 0)
|
||
{
|
||
AfxMessageBox("저장 실패");
|
||
return;
|
||
}
|
||
fprintf_s(fp, "거래 금액 : %d", m_iAmountSet);
|
||
fprintf_s(fp, "매수 조건 최소 : %f", m_fMinPriceSet);
|
||
fprintf_s(fp, "매수 조건 최대 : %f", m_fMaxPriceSet);
|
||
fprintf_s(fp, "매도 요청 : %d", m_iSellTick);
|
||
fprintf_s(fp, "손절 범위 : %d", m_iLossCutTick);
|
||
fprintf_s(fp, "트레일링 범위 : %d", m_iTrailingTick);
|
||
fprintf_s(fp, "취소 시간 : %d", m_iCancelDelay);
|
||
fprintf_s(fp, "풋옵션 : %d", m_bPutOption);
|
||
|
||
fclose(fp);
|
||
fp = NULL;
|
||
}
|
||
|
||
void CCPRobotDlg::LoadFromFile(void)
|
||
{
|
||
FILE* fp = NULL;
|
||
const int iError = fopen_s(&fp, "setting.ini", "rt");
|
||
if(iError != 0)
|
||
return;
|
||
|
||
fscanf_s(fp, "거래 금액 : %d", &m_iAmountSet);
|
||
fscanf_s(fp, "매수 조건 최소 : %f", &m_fMinPriceSet);
|
||
fscanf_s(fp, "매수 조건 최대 : %f", &m_fMaxPriceSet);
|
||
fscanf_s(fp, "매도 요청 : %d", &m_iSellTick);
|
||
fscanf_s(fp, "손절 범위 : %d", &m_iLossCutTick);
|
||
fscanf_s(fp, "트레일링 범위 : %d", &m_iTrailingTick);
|
||
fscanf_s(fp, "취소 시간 : %d", &m_iCancelDelay);
|
||
fscanf_s(fp, "풋옵션 : %d", &m_bPutOption);
|
||
fclose(fp);
|
||
fp = NULL;
|
||
}
|
||
|
||
|
||
// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
|
||
// 아래 코드가 필요합니다. 문서/뷰 모델을 사용하는 MFC 응용 프로그램의 경우에는
|
||
// 프레임워크에서 이 작업을 자동으로 수행합니다.
|
||
|
||
void CCPRobotDlg::OnPaint()
|
||
{
|
||
if (IsIconic())
|
||
{
|
||
CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트
|
||
|
||
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
|
||
|
||
// 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
|
||
int cxIcon = GetSystemMetrics(SM_CXICON);
|
||
int cyIcon = GetSystemMetrics(SM_CYICON);
|
||
CRect rect;
|
||
GetClientRect(&rect);
|
||
int x = (rect.Width() - cxIcon + 1) / 2;
|
||
int y = (rect.Height() - cyIcon + 1) / 2;
|
||
|
||
// 아이콘을 그립니다.
|
||
dc.DrawIcon(x, y, m_hIcon);
|
||
}
|
||
else
|
||
{
|
||
CDialog::OnPaint();
|
||
}
|
||
}
|
||
|
||
// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서 이 함수를 호출합니다.
|
||
HCURSOR CCPRobotDlg::OnQueryDragIcon()
|
||
{
|
||
return static_cast<HCURSOR>(m_hIcon);
|
||
}
|
||
|
||
void CCPRobotDlg::OnBnClickedButtonRefreshBalance()
|
||
{
|
||
// TODO: Add your control notification handler code here
|
||
ICpTdDibPtr pTd0721 = NULL;
|
||
pTd0721.CreateInstance(CLSID_CpTd0721F);
|
||
pTd0721->SetInputValue(0, m_AccountNum.data());
|
||
pTd0721->SetInputValue(1, "50");
|
||
pTd0721->SetInputValue(2, "50");
|
||
pTd0721->SetInputValue(3, "10");
|
||
|
||
CString Message;
|
||
do
|
||
{
|
||
pTd0721->BlockRequest();
|
||
m_iBalance = pTd0721->GetHeaderValue(9);
|
||
|
||
Message.Format("현금주문가능액 : %d", m_iBalance);
|
||
SetDlgItemText(IDC_STATIC_BALANCE, Message.GetString());
|
||
} while(pTd0721->Continue);
|
||
|
||
pTd0721.Release();
|
||
|
||
|
||
LoadFromFile();
|
||
UpdateData(FALSE);
|
||
}
|
||
|
||
void CCPRobotDlg::Subscribe(void)
|
||
{
|
||
const int iCodeCnt = m_OpCodeList.size();
|
||
try
|
||
{
|
||
for(int i=0; i<iCodeCnt; i++)
|
||
{
|
||
m_pOpJpBid->SetInputValue(0, m_OpCodeList[i].data());
|
||
m_pOpJpBid->SubscribeLatest();
|
||
|
||
TRACE1("Subscribe[%s]\n", m_OpCodeList[i].data());
|
||
|
||
if(m_pOpJpBid->GetDibStatus() != 0)
|
||
{
|
||
CString strErrorMsg;
|
||
strErrorMsg += (LPCTSTR)m_pOpJpBid->GetDibMsg1();
|
||
strErrorMsg += (LPCTSTR)m_pOpJpBid->GetDibMsg2();
|
||
strErrorMsg.TrimRight();
|
||
AfxMessageBox(strErrorMsg);
|
||
}
|
||
}
|
||
}
|
||
catch(_com_error e)
|
||
{
|
||
AfxMessageBox("Subscribe Error");
|
||
}
|
||
}
|
||
|
||
void CCPRobotDlg::Unsubscribe(void)
|
||
{
|
||
const int iCodeCnt = m_OpCodeList.size();
|
||
try
|
||
{
|
||
for(int i=0; i<iCodeCnt; i++)
|
||
{
|
||
m_pOpJpBid->SetInputValue(0, m_OpCodeList[i].data());
|
||
m_pOpJpBid->Unsubscribe();
|
||
}
|
||
}
|
||
catch(_com_error e)
|
||
{
|
||
AfxMessageBox("Unsubscribe Error");
|
||
}
|
||
}
|
||
|
||
void CCPRobotDlg::OnBnClickedButtonSearch()
|
||
{
|
||
// TODO: Add your control notification handler code here
|
||
UpdateData();
|
||
|
||
Unsubscribe();
|
||
Subscribe();
|
||
}
|
||
|
||
|
||
void CCPRobotDlg::OnBnClickedButtonStartDeal()
|
||
{
|
||
// TODO: Add your control notification handler code here
|
||
}
|
||
|
||
|
||
void CCPRobotDlg::OnBnClickedRadioBid()
|
||
{
|
||
// TODO: Add your control notification handler code here
|
||
m_bSell = (((CButton*)GetDlgItem(IDC_RADIO_BID))->GetCheck() == 1);
|
||
}
|
||
|
||
void CCPRobotDlg::OnBnClickedRadioAsk()
|
||
{
|
||
// TODO: Add your control notification handler code here
|
||
m_bSell = (((CButton*)GetDlgItem(IDC_RADIO_BID))->GetCheck() == 1);
|
||
}
|
||
|
||
void CCPRobotDlg::Received()
|
||
{
|
||
if(m_pOpJpBid->GetDibStatus() != 0)
|
||
{
|
||
CString strErrorMsg;
|
||
strErrorMsg += (LPCTSTR)m_pOpJpBid->GetDibMsg1();
|
||
strErrorMsg += (LPCTSTR)m_pOpJpBid->GetDibMsg2();
|
||
strErrorMsg.TrimRight();
|
||
AfxMessageBox(strErrorMsg);
|
||
return;
|
||
}
|
||
|
||
string Code = (_bstr_t)m_pOpJpBid->GetHeaderValue(0);
|
||
|
||
float fBid1Price = m_pOpJpBid->GetHeaderValue(19); // 매수 1 우선호가
|
||
int iBid1Cnt = m_pOpJpBid->GetHeaderValue(24); //매수 1 우선호가잔량
|
||
|
||
float afOfferPrice[5];
|
||
afOfferPrice[0] = m_pOpJpBid->GetHeaderValue(2); // 2 - (float) 매도 1 우선호가
|
||
afOfferPrice[1] = m_pOpJpBid->GetHeaderValue(3); // 3 - (float) 매도 2 우선호가
|
||
afOfferPrice[2] = m_pOpJpBid->GetHeaderValue(4); // 4 - (float) 매도 3 우선호가
|
||
afOfferPrice[3] = m_pOpJpBid->GetHeaderValue(5); // 5 - (float) 매도 4 우선호가
|
||
afOfferPrice[4] = m_pOpJpBid->GetHeaderValue(6); // 6 - (float) 매도 5 우선호가
|
||
|
||
|
||
if(m_bPutOption == FALSE && Code[0] == '2')
|
||
{
|
||
if(fBid1Price >= m_fMinPriceSet && fBid1Price <= m_fMaxPriceSet)
|
||
{
|
||
TRACE2("received [%s] %f\n", Code.data(), fBid1Price);
|
||
|
||
Unsubscribe();
|
||
|
||
// 수량 계산
|
||
int iBuyCnt = 1;
|
||
|
||
// 매수 주문
|
||
ICpTdDibPtr pTd6831 = NULL;
|
||
pTd6831.CreateInstance(CLSID_CpTd6831);
|
||
pTd6831->SetInputValue(1, m_AccountNum.data()); // 1 - (string) 계좌번호
|
||
pTd6831->SetInputValue(2, Code.data()); // 2 - (string) 종목코드
|
||
pTd6831->SetInputValue(3, iBuyCnt); // 3 - (long) 주문수량
|
||
pTd6831->SetInputValue(4, afOfferPrice[0]); // 4 - (double) 주문가격
|
||
pTd6831->SetInputValue(5, "2"); // 5 - (string) 매매구분코드 (1:매도, 2:매수)
|
||
pTd6831->SetInputValue(7, "1"); // 7- (string) 주문조건구분코드(0:없음, 1:IOC, 2:FOK)
|
||
|
||
|
||
pTd6831->BlockRequest();
|
||
if(pTd6831->GetDibStatus() != 0)
|
||
{
|
||
CString strErrorMsg;
|
||
strErrorMsg += (LPCTSTR)pTd6831->GetDibMsg1();
|
||
strErrorMsg += (LPCTSTR)pTd6831->GetDibMsg2();
|
||
strErrorMsg.TrimRight();
|
||
TRACE(strErrorMsg);
|
||
}
|
||
|
||
// 매도 요청
|
||
const int iSellAsk = min(m_iSellTick, 4);
|
||
pTd6831->SetInputValue(4, iSellAsk); // 4 - (double) 주문가격
|
||
pTd6831->SetInputValue(5, "1"); // 5 - (string) 매매구분코드 (1:매도, 2:매수)
|
||
pTd6831->SetInputValue(7, "0"); // 7- (string) 주문조건구분코드(0:없음, 1:IOC, 2:FOK)
|
||
|
||
pTd6831->BlockRequest();
|
||
if(pTd6831->GetDibStatus() != 0)
|
||
{
|
||
CString strErrorMsg;
|
||
strErrorMsg += (LPCTSTR)pTd6831->GetDibMsg1();
|
||
strErrorMsg += (LPCTSTR)pTd6831->GetDibMsg2();
|
||
strErrorMsg.TrimRight();
|
||
TRACE(strErrorMsg);
|
||
}
|
||
}
|
||
}
|
||
else if(m_bPutOption == TRUE && Code[0] == '3')
|
||
{
|
||
if(fBid1Price >= m_fMinPriceSet && fBid1Price <= m_fMaxPriceSet)
|
||
{
|
||
TRACE2("received [%s] %f\n", Code.data(), fBid1Price);
|
||
}
|
||
}
|
||
}
|