예스스탁
예스스탁 답변
2018-06-25 16:11:07
안녕하세요
예스스탁입니다.
1
수식 코드 내용을 살펴보았지만 특별히 문제가 될만한 부분이 보이지 않습니다.
올려주신 내용에는 없지만 EntryObject가 제대로 종목객체를 저장하고 있는지 확인해 보셔야 할것 같습니다.
또한 해당 수식에 시세 업데이트마다 수식에서 필요한 값을 출력하셔서
조건만족여부를 파악해 보셔야 합니다.
정리하면 올려주신 코드에서는 특별히 문제가 될만한 내용을 찾지 못했습니다.
종목객체를 저장하므로 종목객체가 지정변수에 제대로 저장되고 있는지 여부를 확인하셔야 하며
BenefitCnt변수 또한 처음에 0으로 시작되게 되어 있는지 확인하셔야 합니다.
최초 1%도달시에 BenefitCnt[i]변수가 0이어야만 동작하므로
BenefitCnt[i]가 0이 아닌 빈공간이면 동작하지 않습니다.
또한 보유수량의 일정%가 1미만이어도 매도가 되지 않습니다.
아래와 같이 종목시세 업데이트시에
사용하는 값을 출력해 확인해 보셔야 합니다.
function Main_OnU*dateMarket(sItemCode, lU*dateID)
{
var d = new Date();
var HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
if( lU*dateID == 20001 && RcvData >= 1 )
{
for( var i = 0; i < EntryItem.length; i++ )
{
if( sItemCode == EntryObject[i].code )
{
A1.SetBalanceItem(EntryObject[i].code, 0);
var UpDown = (EntryObject[i].current - A1.Balance.avgUnitCost)/A1.Balance.avgUnitCost*100;
Main.MessageList(HHMMSS,"|종목코드 : ",EntryObject[i].code,"|현재가 : ",EntryObject[i].current,"|상한가 : ",EntryObject[i].limitUp);
Main.MessageList(HHMMSS,"|보유수량 : ",A1.Balance.count,"평단가 : ",A1.Balance,A1.Balance.avgUnitCost,"|수익률 : ",UpDown);
Main.MessageList(HHMMSS,"|BenefitCnt : ",BenefitCnt[i]);
// 장중 최고가 세팅
if( EntryObject[i].current > EntryHH[i] )
EntryHH[i] = EntryObject[i].current;
// 상한가 도달시 자동 청산
if( EntryObject[i].current >= EntryObject[i].limitUp )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, A1.Balance.count, EntryObject[i].Bid(1), 0);
Main.MessageList("상한가 도달로 익절");
}
}
//1% 도달 - 매수수량의 10% 청산
if( BenefitCnt[i] == 0 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.01 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.1), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 1.5% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 1;
}
//2% 도달 - 매수수량의 20% 청산
if( BenefitCnt[i] == 1 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.02 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.24), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 2% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 2;
}
//3% 도달 - 매수수량의 20% 청산
if( BenefitCnt[i] == 2 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.03 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.32), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 3% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 3;
}
//4% 도달 - 매수수량의 10% 청산
if( BenefitCnt[i] == 3 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.04 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.23), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 3% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 4;
}
//5% 도달 - 매수수량의 10% 청산
if( BenefitCnt[i] == 4 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.05 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.31), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 5% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 5;
}
}
}
}
}
2
메세지로그 메세지리스트는 디버깅창과
예스스팟 화면의 스크립트 메세지 화면에만 출력됩니다.
별도로 파일로 저장하지는 않습니다.
3
일정분주기의 데이터를 사용하려면 차트를 이용하셔야 합니다.
아래 수식 참고해서 기존수식에 보강하시기 바랍니다.
종목검색 후에 검색된 종목의 종목객체를 생성하고
10분 차트를 같이 생성해서 이용하는 내용입니다.
모두 생성되면 이후 차트객체에서 값호출해 원하는 값 계산후 이용하시면 됩니다.
var SearchItem,req;
var EntryObject = [];
var EntryChart = [];
//스팟 시작
function Main_OnStart()
{
//종목검색 요청
Main.ReqPowerSearch("사용자검색조건")
}
//검색완료)
function Main_OnRcvItemList(aItemList, nCount)
{
//검색된 종목을 SearchItem에 저장
SearchItem = aItemList;
//요청갯수는 초기값으로 0을 가짐
req = 0;
//1개 이상의 종목기 검색되었다면
if (SearchItem.length < 0)
{
//종목객체 요청
Main.ReqMarketData(SearchItem[req],0,0);
}
}
//요청한 종목객체 수식
function Main_OnRcvMarketData(MarketData)
{
//요청한 종목과 수신된 종목이 같이면
if (MarketData.code == SearchItem[req])
{
//EntryObject의 req배열방에 종목객체 저장
EntryObject[req] = MarketData;
//요청할 차트객체 셋팅
//종목코드(EntryObject[req].code).주기(10 분), 조회건수(5000 봉),갭보정안함, 수정주가처리 안함
var ChartSet = new ReqChartItem(EntryObject[req].code,10,CHART_PERIOD_MINUTE,5000,CHART_REQCOUNT_BAR,false,false);
//차트객체요청
Main.ReqChartEx(ChartSet);
}
}
//요청한 차트객체 수식
function Main_OnRcvChartEx(ChartEx)
{
//EntryChart의 req배열방에 차트객체 저장
EntryChart[req] = ChartEx;
//req는 1 증가
req = req + 1;
//req가 검색종목수보다 작으면
if (req < SearchItem)
{
//다음종목 종목객체 요청
var S = Main.ReqMarketData(SearchItem[req],0,0);
//제한에 걸려 종목객체 요청이 불가능하면
if (S == -1)
{
//타이머 동작(1번타이머, 20초)
Main.SetTimer(1, 20000);
}
}
else
{
Main.MessageList("객체생성완료");
}
}
//타이머 동작하면
function Main_OnTimer(nEventID)
{
//1번타이머 동작
if (nEventID == 1)
{
//타이머종
Main.KillTimer(1);
//종목객체 재요청
Main.ReqMarketData(SearchItem[req],0,0);
}
}
즐거운 하루되세요
> 도도당 님이 쓴 글입니다.
> 제목 : 매도로직대로 실행이 안돼서 문의드립니다.
> 안녕하세요. 제가 첨으로 예스스팟 게시판 보고 참고해서 프로그램을 완성했는데요.
파워종목 검색으로 주문 넣고 매수 후에 기준가에서 1% 씩 오를때마다 일정수량(10%)을
매도하는 프로그램을 만들었는데요. 종목 검색후 매수(20종목)까지는 무난하게 잘 돌아갑니다.
그런데 익절에서 기준가 대비 1% 상승시 보유수량에 10%, 2% 상승시 보유수량에 20%, 3% 상승시 보유수량에 20%, 4% 상승시 보유수량에 10%, 5% 상승시 보유수량에 10%를 매도하고
10시에 타임컷을 실행하려고 하는데요. 다 잘 돌아가는데 예를 들어 20종목을 매수했는데
어떤 종목은 위 매도로직에 의해 매도가 잘 되는 반면 어떤 종목은 매수가에서 3%까지 상승해도 매도가
안되는 경우가 생기고 해서 뭐가 잘못된건지 모르겠어요ㅜㅜ 매수 종목수가 많아서 그럴까요? 대략 목표치에 도달한 종목중에 10종목중 3종목 정도만 매도 로직대로 매도가 되고 나머지는 매도가 안되고 나중에 타임컷으로 매도가 되었어요. 에러가 뜨면 고치겠는데
에러 메시지가 뜨지도 않으니 뭐가 잘못되었는지 모르겠어요. 코드좀 한번 봐주시기 바랍니다.
그리고 로그 메시지가 따로 저장되는 파일이 존재하나요? 예스스팟에 디버깅이랑 오류창에서만 볼수 있는건가요? 답변좀 부탁드리겠습니다.
그리고 한가지 질문 더 드릴게요.
매도 로직을 하나 더 만들려고 합니다. 분봉을 이용해서 현재 가격 < 30분 and 20분 and 10분 가격 시에 매도하고 싶은데요. 챠트 객체를 이용해서 해야 하나요? 되신다면 간단한 예제좀
부탁드릴게요~ 예스스팟을 배운지 아직 얼마 안돼서 이곳 게시판 보면서 적용하기가
쉽지가 않습니다ㅜㅜ 시간 되시면 답변좀 꼬옥 부탁드려요^^ 감사합니다
function Main_OnU*dateMarket(sItemCode, lU*dateID)
{
if( lU*dateID == 20001 && RcvData >= 1 )
{
for( var i = 0; i < EntryItem.length; i++ )
{
if( sItemCode == EntryObject[i].code )
{
A1.SetBalanceItem(EntryObject[i].code, 0);
// 장중 최고가 세팅
if( EntryObject[i].current > EntryHH[i] )
EntryHH[i] = EntryObject[i].current;
// 상한가 도달시 자동 청산
if( EntryObject[i].current >= EntryObject[i].limitUp )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, A1.Balance.count, EntryObject[i].Bid(1), 0);
Main.MessageList("상한가 도달로 익절");
}
}
//1% 도달 - 매수수량의 10% 청산
if( BenefitCnt[i] == 0 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.01 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.1), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 1.5% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 1;
}
//2% 도달 - 매수수량의 20% 청산
if( BenefitCnt[i] == 1 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.02 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.24), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 2% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 2;
}
//3% 도달 - 매수수량의 20% 청산
if( BenefitCnt[i] == 2 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.03 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.32), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 3% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 3;
}
//4% 도달 - 매수수량의 10% 청산
if( BenefitCnt[i] == 3 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.04 )
{
if( A1.Balance.count >= 1 )
{
A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.23), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 3% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 4;
}
//5% 도달 - 매수수량의 10% 청산
if( BenefitCnt[i] == 4 && EntryObject[i].current >= A1.Balance.avgUnitCost * 1.05 )
{
if( A1.Balance.count >= 1 )
{ A1.OrderSell(A1.Balance.code, Math.floor(A1.Balance.count * 0.31), EntryObject[i].Ask(1), 0);
Main.MessageList("종목명 : ", EntryObject[i].name, " 진입가에서 5% 상승하여 전체 금액의 10% 익절");
}
BenefitCnt[i] = 5;
}
}
}
}
}