예스스탁
예스스탁 답변
2013-08-28 10:45:59
안녕하세요
예스스탁입니다.
식작성에 아래식 참고하시기 바랍니다.
1. 스크립트 객체화면 설정
차트객체 - Chart1, 속성에서 차트와 아이디 연동, 이동평균 지표적용
계좌객체 - Account1
종목객체 - MarketData1, 속성에서 차트와 같은 종목으로 지정
2.
차트에서 이평 상태를 알기 위해서는 첨부된그림과 같이 이동평균선이 적용된 상태여야 합니다.
3.
주문수량이 여러개 이면 한번에 체결이 되지 않거나 일부체결만 되면
수식이 복잡해 답변드리기 어려우므로 주문수량은 모두 1로 지정했습니다.
var P_1B = 0; // signalKind 1, 즉 매수신호 발생에 따라, OrderBuy를 한 매수주문 가격을 저장
var ID_1B = 0; // 매수진입 주문ID
var ON_1B = 0; // 매수진입 주문번호
var ID_1BX = 0;// 매수진입 취소주문ID
var ID_1S = 0; // 매수청산 주문ID
var ON_1S = 0; // 매수청산 주문번호
var ID_1SX = 0; // 매수청산 취소주문ID
var Step = 0; //등 미체결, 미결제가 다 처리된 후 새로운 신규 매수진입이 가능하도록 해 주는 변수.
function Main_OnStart()
{
step = 0; //스팟 시작시 step은 0
}
function Chart1_OnRiseSignal(Signal)
{
//Step이 0인 상태에서 매수신호 발생
if (Step == 0 && Signal.signalKind == 1)
{
P_1B = MarketData1.Ask(5);//매도5호가
ID_1B = Account1.OrderBuy(Main.GetOrderCode(MarketData1.code),1,P_1B, 0);
Step = 1; //Step은 1
//3번 타이머 셋팅
Main.SetTimer(3, 3000); //3초 간격
}
}
//주문응답
function Main_OnOrderResponse(OrderResponse)
{
//ID_1B와 같은 아이디를 가지는 주문응답이 수신되면
if (Step == 1 && OrderResponse.orderID == ID_1B)
{
//주문번호 저장
ON_1B = OrderResponse.orderNum;
}
//ID_1S와 같은 아이디를 가지는 주문응답이 수신되면
if (Step == 1 && OrderResponse.orderID == ID_1S)
{
//주문수량이 0이상이고 주문에러가 없으면
if (OrderResponse.orderCount > 0 && OrderResponse.error == "")
{
//주문번호 저장
ON_1S = OrderResponse.orderNum;
//타이머 셋팅
Main.SetTimer(1, 60000);//60초
Main.SetTimer(2, 120000); //120초
}
}
//매수청산 취소주문응답 수신
if ( Step == 1 && OrderResponse.orderID == ID_1SX)
{
//주문수량이 0이고 주문에러가 없으면
if (OrderResponse.orderCount == 0 && OrderResponse.error == "")
{
//시장가로 주문
ON_1S= Account1.OrderSell(Main.GetOrderCode(MarketData1.code), 1, 0, 1);
}
}
//매수주문 취소주문응답 수신
if ( Step == 1 && OrderResponse.orderID == ID_1BX)
{
//주문수량이 0이고 주문에러가 없으면
if (OrderResponse.orderCount == 0 && OrderResponse.error == "")
{
step = 0; //step 0 초기화
}
}
}
//체결응답
function Main_OnNotifyFill(NotifyFill)
{
//ON_1B와 같은 주문번호가 체결되면
if (Step == 1 && NotifyFill.orderNum == ON_1B)
{
//익절주문 - 주문가격+5틱으로 매도주문 발생
ID_1S = Account1.OrderSell(Main.GetOrderCode(MarketData1.code), 1, P_1B+MarketData1.GetTickSize()*5, 0);
}
//ON_1S와 같은 주문번호가 체결되면
if (Step == 1 && NotifyFill.orderNum == ON_1S)
{
step = 0; //step 0 초기화
}
}
function Main_OnTimer(nEventID)
{
//1번 타이머 동작
if (Step == 1 && nEventID == 1)
{
Main.KillTimer(1); //1번 타이머 중지
//ON_1S 미체결 객체 셋팅
Account1.SetUnfillOrderNumber(ON_1S);
//미체결 객체수량이 0이상이면(미체결이 있음)
if (Account1.Unfill.count > 0)
{
//현재가로 정정주문
ID_1S = Account1.OrderReplacePrice(ON_1S, MarketData1.current);
}
}
//2번 타이머 동작
if (Step == 1 && nEventID == 2)
{
Main.KillTimer(2); //2번 타이머 중지
//ON_1S 미체결 객체 셋팅
Account1.SetUnfillOrderNumber(ON_1S);
//미체결 객체 수량이 0이상이면(미체결이 있음)
if (Account1.Unfill.count > 0)
{
//취소주문
ID_1SX = Account1.OrderCancel(ON_1S);
}
}
//3번 타이머 동작
if (Step == 1 && nEventID == 3)
{
//매수주문 미체결 객체 셋팅
Account1.SetUnfillOrderNumber(ON_1B);
//ON_1B 주문번호의 미체결수량이 0이상이고 (미체결이 있음)
//단수이동평균2 지표의 plot1이 plot2보다 작으면 취소주문
if (Account1.Unfill.count > 0 &&
Chart1.GetIndicatorData("단순이동평균2",1,0) < Chart1.GetIndicatorData("단순이동평균2",2,0) )
{
ID_1BX = Account1.OrderCancel(ON_1B);
Main.KillTimer(3); //3번 타이머 중
}
}
}
2
추가로 문의하신 부분은 따로 객관화된 내용이 있는 부분이 아니고
따로 통계적인 데이터도 없어 답변을 드리기 어렵습니다.
도움을 드리지 못해 죄송합니다.
즐거운 하루되세요
> 즐겁게 님이 쓴 글입니다.
> 제목 : 문의 올립니다.
> 안녕하십니까? 항상 친절하신 답변에 깊이 감사드립니다.
예스랭귀지로 구현한 시스템 전략은 어느 정도 최소한 제게는 만족스럽게 정리가 되었는데,
이와 함께 사용할 스팟 전략을 짜고 있는 중입니다.
대략 아래와 같은 흐름을 가지고 스팟을 코딩하는 중인데,
저 스스로 제가 하고 있는 것이 제대로 하고 있는 것인지도 궁금하고,
막히기도 하고 해서, 전문적인 가르침을 받고자 질문 글 올립니다.
아래의 흐름을 기반으로 소스를 짜려고 하는데,
각종 function들 속에서, 어떻게 명령들을 구현하는 것이 좋을지,
길을 제시하여 주시면 대단히 감사하겠습니다.
흐름:
<<<<<<<<<< <<<<<<<<<< <<<<<<<<<< <<<<<<<<<< <<<<<<<<<< <<<<<<<<<< <<<<<<<<<<
1. 차트에서 매수신호 발생 (예를 들어, 이평선 두 개가 이제 막 정배열로 됨) (이 전체 모델에서, 단순화를 위해, 신호발생은 매수신호만 있는 걸로 가정함)
2. 매수주문함. (OnRiseSignal. 주문ID: ID_1B, 주문가격: P_1B)
3. 이 매수주문이 체결되는 경우(아래 4)과 미체결된 경우(아래 8)로 구분.
4. 매수주문이 체결되면: 익절(ProfitTarget) 매수청산주문 발주. 매수가격보다 5틱 위 가격으로 매수청산 주문. (아마도 OnNotifyFill 사용?)
5. 이 익절 매수청산주문이 체결되는 경우(아래 6)와, 안 되는 경우(아래 7)로 구분.
6. 익절 매수청산주문이 체결되는 경우 (아마도 OnNotifyFill 사용?): 전체과정 종료 (다음 새로운 매수신호에 따라 신규매수주문이 가능하도록 함. 미체결주문도 없고, 미결제잔고도 없다는 것을 변수들[Step = 0, U_1B = 0, U_1S = 0, BC_L = 0 등]을 이용해서 변수들에 저장해서, 전체과정이 위의 1번에서부터 새롭게 시작할 수 있도록 해 줌)
7. 익절 매수청산주문이 체결되지 않은 경우 (아마도 OnTimer 사용?): 반드시 체결되도록 함. (즉 매수청산주문이 체결되어야만 일단 전체과정이 종료되고, 다음 새로운 매수신호에 따라 신규매수주문이 가능하게 함).
* (매수가격+5틱 지정가로 했던) 매수청산주문이 발주된 지
* 1분이 지나도 체결되지 않으면, 현재가로 매수청산주문을 정정주문함.
* 2분이 지나도 체결되지 않으면, 시장가로 매수청산주문을 다시 냄. (원 주문을 취소하고, 새로 시장가 매수청산 주문 발주)
8. 매수주문이 미체결된 경우는 다시 매수주문 발주 당시 상황이 지금도 유지되는 경우와, 그렇지 않은 경우로 구분함. (아마도 OnTimer 사용?) (타이머로 3초마다 체크, 그에 따른 처리를 계속함. 아래와 같이.)
9. 매수주문 미체결시, 발주 당시 상황이 지금도 유지되는 경우 (예를 들어, 지금도 차트에서 이평선 두 개가 정배열 상태 유지): 아무 것도 안하고, 이미 발주한 매수주문이 체결되기를 기다리기만 함.
10. 매수주문 미체결시, 발주 당시 상황이 이제 변해 버린 경우 (예를 들어, 차트에서 이평선 두 개가 이제 역배열로 바뀌어 버림): 기존 미체결 매수주문을 취소해 버림.
>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>>
* 아마도
function C1_OnRiseSignal(Signal) 속에 위의 2번을 넣고,
function Main_OnNotifyFill(NotifyFill) 속에 위의 4번과 6번을 넣고,
function Main_OnTimer(nEventID) 속에 위의 7, 9, 10을 넣으면 되지 않겠나 생각합니다만,
function Main_OnUp*dateMarket은 위의 경우에 굳이 사용하지 않아도 괜찮은 것인지
구체적으로는 어떻게 코딩을 하면 좋겠는지
위 줄거리와 위 함수들을 어떻게 조화시키는 것이 최적이겠는지
등등이 궁금합니다.
시간이 허용되시는 한도내에서 자세히 알려 주시면 대단히 감사하겠습니다.
대단히 감사합니다.
********** ********** ********** ********** ********** ********** **********
PS.
죄송하지만 추가 질문 하나 더 드리고 싶습니다.
스팟 작업을 하면서, 시뮬레이션과 최적화 작업을 할 수 없다 보니, 항상 아래와 같은 부분에서 어려움을 느낍니다.
가령
타이머를 쓸 때에, 시간을 얼마로 할 것인지, 가령 위 내용 중에, 1분이나 2분 체결을 기다려 보고 체결이 안 되면 정정이나 취소를 한다든지,
또는
진입신호 가격으로 매수진입 주문이 체결된 후에는, 가령 매수진입가격의 5틱 위의 값으로 목표이익 청산주문을 넣든다든지 할 때에,
과연 1분 2분 또는 10분 등 어느 시간 만큼 기다려 보도록 하는 것이 가장 좋을지, 목표이익 값은 스팟에서 결정할 때에 몇 틱 위 값으로 하는 것이 최적이겠는지, 손절값은 몇 틱 아래로 하는 것이 좋겠는지를 객관적으로 알 수가 없으니 저로서는 일단 어느 정도 생각 후에 직관적으로 결정하는, 요컨대 대충 주관적으로 결정하는 수 밖에 없습니다.
이렇게 Timer에서의 시간을 정할 때에, 수익률을 극대화할 수 있는 시간을 정할 수 있는 좋은 지침(가능하다면 최대한 검증이 가능한...) 방법이 없을른지요?
(마찬가지로, 스팟 상에서 익절 폭이나 손절 폭을 가장 합리적으로, 즉 수익률이 극대화될 수 있도록 정하는 좋은 방법은 없을지요?)
대단히 감사합니다!