예스스탁
예스스탁 답변
2016-12-15 15:52:25
> gt 님이 쓴 글입니다.
> 제목 : 수식문의
> 올려져 있는식 조금 수정해서 사용중입니다.
0. 며칠 돌려보니 문제점이 좀 있습니다.
종목검색된후 EntryItem에 하나하나 쌓이는데, 예스스팟을 재가동한다던지, YT를 재접속할 경우 EntryItem에 쌓인 종목들이 모두 없어집니다. 따라서 Start()에서 현재 잔고에 있는 종목들을 먼저 파악후 EntryItem에 넣어주는 작업 등이 선행되어야 할 듯 합니다. EntryObject, EntryPrice 등의 정보도 ....더 좋은 방법 있으면 알려주시면 감사하겠습니다. 파일로 저장해서 가지고 있는 방법보다 잔고확인이 더 좋을 듯 싶은데...
그리고 Req의 사용 목적은 무엇인가요? 어디 선언된 곳도 없는데... DataReq는 종목데이타를 요청했는지 구분하려고 하는 거 같고...
1. 검색되는 종목을 모두 동적으로 1분차트 생성하고, AA이평선지표 적용, AA지표 20MA를 -2틱으로 깨면 보유중인 종목 중 해당 종목을 강제청산하고 미체결주문이 있을 경우 취소하고자 합니다. 이후 강제청산된 종목은 동적생성된 차트를 제거합니다. 수식부탁드립니다. 혹 동적으로 차트 생성하지 않고도 AA지표의 20MA를 계산하여 적용가능한지요? 만약 가능하다면 이 방법으로 기술부탁드립니다.
참고로 확장차트는 시스템을 적용하지 않고 오직 청산이나 손절의 목적으로 사용하려고 합니다.
2. 종목검색이후 매수주문을 2번에 걸쳐 하는데, 하나는 매도호가 1호가에 하나는 매수호가 3호가에 주문을 넣습니다. 만약 5분후 주문 체결이 안된것이 있으면 취소하고자 합니다.
3. 잔고와 시세가 변경되는 걸 감시하면서 진입된 종목명, 수량, 진입시간, 진입이후 최고가, 진입이후 최고수익률, 청산시간, 최종수익률을 엑셀에 기입하고 당일 모니터링하고자 합니다. 날짜별로 엑셀시트를 변경하여 기록으로 남기고 싶습니다. 수식을 추가부탁드립니다.
4. 매도#2 부분이 정상적으로 작동되지 않더군요. 진입이후 최고가 대비 3% 빠지면 청산하는 것인데, 어떤 종목은 진입하자마자 청산이 되더군요. 관찰해보니 고가대비 3%하락하면 진입했다가 바로 청산되더군요.
5. 시간여력이 되신다면 주석도 부탁드리겠습니다. 추후 많은 도움이 될 듯 합니다.
6. SendInterest() 함수와 반대로, 관심종목에 있는 종목을 삭제 또는 편입된 종목을 체크하는 기능은 없는지요?
다소질문이 많습니다. 아직 프로그래밍이 미숙해서 도움요청을 드립니다.
바쁘시겠지만 부탁드립니다.
var EntryMoney; // 총 예수금
var ItemList; // 종목검색후 종목리스트 저장변수
var Count; // 종목검색후 종목수 저장변수
var EntryObject = []; // 종목객체 저장
var EntryItem = []; // 종목코드 저장
var EntryHH = []; // 종목최고가 저장
var EntryPrice = []; // 종목진입가 저장
var LossCnt = []; // ?
var EntryCnt = 0; // ?
var RcvData = 0; // ?
var Search = false; // 종목검색 여부
var DataReq = false; // ?
var DayX = false; // ?
//스팟시작
function Main_OnStart()
{
//Main.MessageLog("----------------------------------------------------------------------------------------");
Main.MessageLog("+STOCK FIND GETs READY!");
//Main.MessageLog("----------------------------------------------------------------------------------------");
var d = new Date();
var YYYYMMDD = d.getFullYear() * 10000 + (d.getMonth() + 1) * 100 + d.getDate();
var HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
Main.SetTimer(1, 5000); // 타이머 설정 2s
Search = false;
DataReq = false;
DayX = false;
RcvData = 0;
// 계좌 예수금 조회
EntryMoney = Math.floor(Account1.GetBalanceETCinfo(0));
}
function Main_OnTimer(nEventID)
{
var d = new Date();
var YYYYMMDD = d.getFullYear() * 10000 + (d.getMonth() + 1) * 100 + d.getDate();
var HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
if (HHMMSS > 090100 && HHMMSS < 152000)
{
//1번 타이머동작하면 사용자검색조건 실행
if (nEventID == 1 && Search == false)
{
Main.MessageList("검색요청");
Main.ReqPowerSearch("#PowerSearch");
Req = 0;
Search = true;
DataReq = false;
}
if (nEventID == 2 && Req == Count)
{
Main.MessageList("요청종료");
Search = false;
Main.KillTimer(2);
}
if (nEventID == 2 && Req < Count && Search == true && DataReq == false)
{
Main.MessageList("요청전 EntryItem: ", EntryItem);
var Entry = false;
for (var i = 0; i < EntryItem.length; i++)
{
if (EntryItem[i] == ItemList[Req])
{
Entry = true;
}
}
if (Entry == false)
{
Main.ReqMarketData(ItemList[Req], 0, 0);
Main.MessageList("요청: ",ItemList[Req],Req);
}
if (Entry == true)
{
Main.MessageList("요청x: ",ItemList[Req]);
}
Req = Req + 1;
}
}
}
//종목검색이 완료
function Main_OnRcvItemList(aItemList, nCount)
{
var d = new Date();
var YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate();
var HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//검색종목수가 1개 이상이면
if (nCount >= 1 && DataReq == false)
{
ItemList = aItemList;
Count = nCount;
Main.MessageList("검색완료: ", ItemList);
//종목객체 생성 요청
var Entry = false;
for(var i = 0; i < EntryItem.length; i++)
{
if (EntryItem[i] == ItemList[Req])
{
Entry = true;
}
}
if (Entry == false)
{
DataReq = true;
Main.ReqMarketData(ItemList[Req], 0, 0);
Main.MessageList("요청 마켓데이타: ", ItemList[Req], Req);
// 시세 관심종목에 보내기
Main.SendInterests("관심시세[" + YYYYMMDD + "]", aItemList, true); // true: 종목추가, false: 종목대체
//Main.MessageLog("----------------------------------------------------------------------------------------");
Main.MessageLog("+Send Interests [" + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + "]");
//Main.MessageLog("----------------------------------------------------------------------------------------");
}
if (Entry == true)
{
DataReq = false;
Main.MessageList("잔고편입중 요청안함: ", ItemList[Req]);
}
Req = Req + 1;
Main.SetTimer(2, 5000); //간격(1초)
}
else
{
Main.MessageList("검색종목 없어 5초후 재검색");
Search = false;
}
}
//요청한 종목객체가 생성되면
function Main_OnRcvMarketData(MarketData)
{
EntryItem[RcvData] = MarketData.code;
EntryObject[RcvData] = MarketData;
Account1.SetBalanceItem(MarketData.code,0);
//1주 단위일 경우
Main.MessageList("종목수신:" ,EntryObject[RcvData]);
if (Account1.Balance.count == 0)
{
var Vol = 0;
Vol = Math.floor(EntryMoney / EntryObject[RcvData].Ask(5));
Main.MessageList("종목수량:", EntryMoney, Vol);
if (Vol > 0)
{
EntryHH[RcvData] = EntryObject[EntryCnt].current;
EntryPrice[RcvData] = EntryObject[EntryCnt].current;
LossCnt[RcvData] = 0;
Main.MessageList("주문:",EntryObject[RcvData].code);
// 매도 1호가에 주문접수
Account1.OrderBuy(EntryObject[RcvData].code, 1, EntryObject[RcvData].Ask(1), 0);
}
}
RcvData = RcvData + 1;
DataReq = false;
}
//생성된 종목들의 시세수신
function Main_OnUp*dateMarket(sItemCode, lUp*dateID)
{
var d = new Date();
var HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
//15시 19분에 잔고에 있는 종목 전량 청산(당일청산)
if (DayX == false && HHMMSS >= 151900 && RcvData >= 1)
{
DayX = true;
// 타이머 삭제
Main.KillTimer(1);
var num = Account1.GetTheNumberOfBalances();
for(var i = 0; i < num; i++)
{
Account1.SetBalanceIndex(i);
// 매도
if (Account1.Balance.position == 1)
{
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
}
// 매수포지션이면
if (Account1.Balance.position == 2)
{
// 시장가 청산
Account1.OrderSell(Account1.Balance.code, Account1.Balance.count,0,1);
Main.MessageList("매도#1: ", Account1.Balance.code);
}
}
}
if (lUp*dateID == 20001 && HHMMSS < 153000 && RcvData >= 1)
{
for(var i = 0; i < EntryItem.length; i++)
{
if (sItemCode == EntryObject[i].code)
{
//진입이후 최고가
if (EntryObject[i].current > EntryHH[i])
EntryHH[i] = EntryObject[i].current;
/* //진입이후 최고가 -3%
if (EntryObject[i].current <= EntryHH[i]*0.97)
{
Account1.SetBalance(EntryObject[i].code , 0);
if (Account1.Balance.count > 0)
{
//Account1.OrderSell(Account1.Balance.code,Account1.Balance.count, EntryObject[i].Bid(5),0);
Main.MessageList("매도#2: ", Account1.Balance.code);
}
}*/
//상한가 청산
if (EntryObject[i].current >= EntryObject[i].limitUp)
{
Account1.SetBalance(EntryObject[i].code, 0);
if (Account1.Balance.count > 0)
{
Account1.OrderSell(Account1.Balance.code, Account1.Balance.count, EntryObject[i].Bid(5),0);
Main.MessageList("매도#3: ", Account1.Balance.code);
}
}
}
}
}
}
예스스탁
예스스탁 답변
2016-12-16 17:12:03
안녕하세요
예스스탁입니다.
0.
스팟은 변수에 값이 저장되면 실행중에만 값이 저장되고
재실행되거나 해제하면 사라지게 됩니다.
남기고자 하시는 값이 잔고에서 확인할수 있는 값이면
잔고셋팅 후 필요한 값을 가져와 변수에 추가하면 되지만
var num = Account1.GetTheNumberOfBalances();
for (i = 0; i < num; i++)
{
Account1.SetBalanceIndex(i);
EntryItem[i] = Account1.Balance.code;
EntryPrice[i] = Account1.Balance.avgUnitCost;
}
진입이후 최고가와 같이 잔고에서는 확인할수 없는 내용은
Main.SetUserValue(sName, sValue)로 저장 후 필요한 시점에
Main.GetUserValue(sName)로 값을 가져와 사용해야 합니다.
수식에서 사용되는데 선언이 없는 변수는 상단에 선언을 추가해 주시면 됩니다.
반대로 선언되어 있는 변수인데 수식에서 사용하지 않으면 삭제하시기 바랍니다.
1
특정분봉 주기의 데이타는 차트객체에서만 제공됩니다.
다른 방법이 있지는 않습니다.
확장차트함수(Main.ReqChartEx)로
원하시는 종목에 대한 정보와 필요한 예스랭귀지 지표를 지정해서
확장차트를 만든 후에 수식에서 이용하게 하셔야 합니다.
확장차트를 삭제하는 기능은 현재 제공되고 있지 않습니다.
2
주문을 내는 시점에 타이머를 설정하고
타이머가 동작하면 미체결확인후 취소하시면 됩니다.
이벤트
{
if (조건)
{
// 매도 1호가에 주문접수
Account1.OrderBuy(EntryObject[RcvData].code, 1, EntryObject[RcvData].Ask(1), 0);
Account1.OrderBuy(EntryObject[RcvData].code, 1, EntryObject[RcvData].Bid(1), 0);
Main.SetTimer(99,300000);//99번 타이머 300초
}
}
function Main_OnTimer(nEventID)
{
if (nEventID == 99)
{
Main.KillTimer(99);//타이머 종료
var num = Account1.GetTheNumberOfUnfills();//미체결 주문 갯수
for (var i = 0; i < num; i++)
{
//순차적으로 미체결 객체 셋팅해서
Account1.SetUnfillIndex(i);
//미체결 수량이 있고 매수주문이면 취소
if (Account1.Unfill.count > 0 && Account1.Unfill.orderKind == 2)
{
Account1.OrderCancel(Account1.Unfill.orderNum);
}
}
}
}
3
스팟에 엑셀객체가 제공됩니다.
특정 엑셀파일을 지정후 쉬트를 지정해 특정셀에 값을 저장할수는 있습니다.
다만 스팟에서 쉬트는 생성을 할수 없어 날짜별로 쉬트관리가 되지는 않아
문의하신 부분은 가능하지 않을것 같습니다.
4
매도2는 현재가가 EntryHH[i]에 저장된 값 대비 3% 이하이면 청산이 됩니다.
EntryHH[i]최초에 해당 종목의 현재값이후 이후 값을 갱신해 값니다.
해당 부분은 각 EntryHH에 정상값이 저장되는지 메세지로그로 출력해 보셔야 할것 같습니다.
5
관심종목의 종목을 삭제하거나 체크하는 기능은 없습니다.
문의하신 부분은 건의하도록 하겠습니다.
6.
업무관계로 답변을 자세히 드리지 못해 죄송합니다.
스팟이 계속 테스트 하면서 작성해 보아야 하고
내용에 따라 여러곳에서 제어를 해야하므로 수식을 답변드리기는 어렵습니다.
식 작성하시다가 안풀리는 부분이 있으시면 전화주시면 원격으로 그때그때 대응해 드리도록 하겠습니다.
즐거운 하루되세요
> gt 님이 쓴 글입니다.
> 제목 : 수식문의
> 올려져 있는식 조금 수정해서 사용중입니다.
0. 며칠 돌려보니 문제점이 좀 있습니다.
종목검색된후 EntryItem에 하나하나 쌓이는데, 예스스팟을 재가동한다던지, YT를 재접속할 경우 EntryItem에 쌓인 종목들이 모두 없어집니다. 따라서 Start()에서 현재 잔고에 있는 종목들을 먼저 파악후 EntryItem에 넣어주는 작업 등이 선행되어야 할 듯 합니다. EntryObject, EntryPrice 등의 정보도 ....더 좋은 방법 있으면 알려주시면 감사하겠습니다. 파일로 저장해서 가지고 있는 방법보다 잔고확인이 더 좋을 듯 싶은데...
그리고 Req의 사용 목적은 무엇인가요? 어디 선언된 곳도 없는데... DataReq는 종목데이타를 요청했는지 구분하려고 하는 거 같고...
1. 검색되는 종목을 모두 동적으로 1분차트 생성하고, AA이평선지표 적용, AA지표 20MA를 -2틱으로 깨면 보유중인 종목 중 해당 종목을 강제청산하고 미체결주문이 있을 경우 취소하고자 합니다. 이후 강제청산된 종목은 동적생성된 차트를 제거합니다. 수식부탁드립니다. 혹 동적으로 차트 생성하지 않고도 AA지표의 20MA를 계산하여 적용가능한지요? 만약 가능하다면 이 방법으로 기술부탁드립니다.
참고로 확장차트는 시스템을 적용하지 않고 오직 청산이나 손절의 목적으로 사용하려고 합니다.
2. 종목검색이후 매수주문을 2번에 걸쳐 하는데, 하나는 매도호가 1호가에 하나는 매수호가 3호가에 주문을 넣습니다. 만약 5분후 주문 체결이 안된것이 있으면 취소하고자 합니다.
3. 잔고와 시세가 변경되는 걸 감시하면서 진입된 종목명, 수량, 진입시간, 진입이후 최고가, 진입이후 최고수익률, 청산시간, 최종수익률을 엑셀에 기입하고 당일 모니터링하고자 합니다. 날짜별로 엑셀시트를 변경하여 기록으로 남기고 싶습니다. 수식을 추가부탁드립니다.
4. 매도#2 부분이 정상적으로 작동되지 않더군요. 진입이후 최고가 대비 3% 빠지면 청산하는 것인데, 어떤 종목은 진입하자마자 청산이 되더군요. 관찰해보니 고가대비 3%하락하면 진입했다가 바로 청산되더군요.
5. 시간여력이 되신다면 주석도 부탁드리겠습니다. 추후 많은 도움이 될 듯 합니다.
6. SendInterest() 함수와 반대로, 관심종목에 있는 종목을 삭제 또는 편입된 종목을 체크하는 기능은 없는지요?
다소질문이 많습니다. 아직 프로그래밍이 미숙해서 도움요청을 드립니다.
바쁘시겠지만 부탁드립니다.
var EntryMoney; // 총 예수금
var ItemList; // 종목검색후 종목리스트 저장변수
var Count; // 종목검색후 종목수 저장변수
var EntryObject = []; // 종목객체 저장
var EntryItem = []; // 종목코드 저장
var EntryHH = []; // 종목최고가 저장
var EntryPrice = []; // 종목진입가 저장
var LossCnt = []; // ?
var EntryCnt = 0; // ?
var RcvData = 0; // ?
var Search = false; // 종목검색 여부
var DataReq = false; // ?
var DayX = false; // ?
//스팟시작
function Main_OnStart()
{
//Main.MessageLog("----------------------------------------------------------------------------------------");
Main.MessageLog("+STOCK FIND GETs READY!");
//Main.MessageLog("----------------------------------------------------------------------------------------");
var d = new Date();
var YYYYMMDD = d.getFullYear() * 10000 + (d.getMonth() + 1) * 100 + d.getDate();
var HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
Main.SetTimer(1, 5000); // 타이머 설정 2s
Search = false;
DataReq = false;
DayX = false;
RcvData = 0;
// 계좌 예수금 조회
EntryMoney = Math.floor(Account1.GetBalanceETCinfo(0));
}
function Main_OnTimer(nEventID)
{
var d = new Date();
var YYYYMMDD = d.getFullYear() * 10000 + (d.getMonth() + 1) * 100 + d.getDate();
var HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
if (HHMMSS > 090100 && HHMMSS < 152000)
{
//1번 타이머동작하면 사용자검색조건 실행
if (nEventID == 1 && Search == false)
{
Main.MessageList("검색요청");
Main.ReqPowerSearch("#PowerSearch");
Req = 0;
Search = true;
DataReq = false;
}
if (nEventID == 2 && Req == Count)
{
Main.MessageList("요청종료");
Search = false;
Main.KillTimer(2);
}
if (nEventID == 2 && Req < Count && Search == true && DataReq == false)
{
Main.MessageList("요청전 EntryItem: ", EntryItem);
var Entry = false;
for (var i = 0; i < EntryItem.length; i++)
{
if (EntryItem[i] == ItemList[Req])
{
Entry = true;
}
}
if (Entry == false)
{
Main.ReqMarketData(ItemList[Req], 0, 0);
Main.MessageList("요청: ",ItemList[Req],Req);
}
if (Entry == true)
{
Main.MessageList("요청x: ",ItemList[Req]);
}
Req = Req + 1;
}
}
}
//종목검색이 완료
function Main_OnRcvItemList(aItemList, nCount)
{
var d = new Date();
var YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate();
var HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
//검색종목수가 1개 이상이면
if (nCount >= 1 && DataReq == false)
{
ItemList = aItemList;
Count = nCount;
Main.MessageList("검색완료: ", ItemList);
//종목객체 생성 요청
var Entry = false;
for(var i = 0; i < EntryItem.length; i++)
{
if (EntryItem[i] == ItemList[Req])
{
Entry = true;
}
}
if (Entry == false)
{
DataReq = true;
Main.ReqMarketData(ItemList[Req], 0, 0);
Main.MessageList("요청 마켓데이타: ", ItemList[Req], Req);
// 시세 관심종목에 보내기
Main.SendInterests("관심시세[" + YYYYMMDD + "]", aItemList, true); // true: 종목추가, false: 종목대체
//Main.MessageLog("----------------------------------------------------------------------------------------");
Main.MessageLog("+Send Interests [" + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + "]");
//Main.MessageLog("----------------------------------------------------------------------------------------");
}
if (Entry == true)
{
DataReq = false;
Main.MessageList("잔고편입중 요청안함: ", ItemList[Req]);
}
Req = Req + 1;
Main.SetTimer(2, 5000); //간격(1초)
}
else
{
Main.MessageList("검색종목 없어 5초후 재검색");
Search = false;
}
}
//요청한 종목객체가 생성되면
function Main_OnRcvMarketData(MarketData)
{
EntryItem[RcvData] = MarketData.code;
EntryObject[RcvData] = MarketData;
Account1.SetBalanceItem(MarketData.code,0);
//1주 단위일 경우
Main.MessageList("종목수신:" ,EntryObject[RcvData]);
if (Account1.Balance.count == 0)
{
var Vol = 0;
Vol = Math.floor(EntryMoney / EntryObject[RcvData].Ask(5));
Main.MessageList("종목수량:", EntryMoney, Vol);
if (Vol > 0)
{
EntryHH[RcvData] = EntryObject[EntryCnt].current;
EntryPrice[RcvData] = EntryObject[EntryCnt].current;
LossCnt[RcvData] = 0;
Main.MessageList("주문:",EntryObject[RcvData].code);
// 매도 1호가에 주문접수
Account1.OrderBuy(EntryObject[RcvData].code, 1, EntryObject[RcvData].Ask(1), 0);
}
}
RcvData = RcvData + 1;
DataReq = false;
}
//생성된 종목들의 시세수신
function Main_OnUp*dateMarket(sItemCode, lUp*dateID)
{
var d = new Date();
var HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
//15시 19분에 잔고에 있는 종목 전량 청산(당일청산)
if (DayX == false && HHMMSS >= 151900 && RcvData >= 1)
{
DayX = true;
// 타이머 삭제
Main.KillTimer(1);
var num = Account1.GetTheNumberOfBalances();
for(var i = 0; i < num; i++)
{
Account1.SetBalanceIndex(i);
// 매도
if (Account1.Balance.position == 1)
{
Account1.OrderBuy(Account1.Balance.code, Account1.Balance.count,0,1);
}
// 매수포지션이면
if (Account1.Balance.position == 2)
{
// 시장가 청산
Account1.OrderSell(Account1.Balance.code, Account1.Balance.count,0,1);
Main.MessageList("매도#1: ", Account1.Balance.code);
}
}
}
if (lUp*dateID == 20001 && HHMMSS < 153000 && RcvData >= 1)
{
for(var i = 0; i < EntryItem.length; i++)
{
if (sItemCode == EntryObject[i].code)
{
//진입이후 최고가
if (EntryObject[i].current > EntryHH[i])
EntryHH[i] = EntryObject[i].current;
/* //진입이후 최고가 -3%
if (EntryObject[i].current <= EntryHH[i]*0.97)
{
Account1.SetBalance(EntryObject[i].code , 0);
if (Account1.Balance.count > 0)
{
//Account1.OrderSell(Account1.Balance.code,Account1.Balance.count, EntryObject[i].Bid(5),0);
Main.MessageList("매도#2: ", Account1.Balance.code);
}
}*/
//상한가 청산
if (EntryObject[i].current >= EntryObject[i].limitUp)
{
Account1.SetBalance(EntryObject[i].code, 0);
if (Account1.Balance.count > 0)
{
Account1.OrderSell(Account1.Balance.code, Account1.Balance.count, EntryObject[i].Bid(5),0);
Main.MessageList("매도#3: ", Account1.Balance.code);
}
}
}
}
}
}