스팟의 변수는 휘발성입니다.
전략 실행 중에만 저장한 값을 기억하게 되고 종료되면 사라지게 됩니다.
프로그램은 매일 아침에 초기화를 진행하여 재접속을 하게 되므로
변수값을 저장해 다음날이나 재접속 이후에도 재사용하고 하면
별도로 내부파일에 저장해서 이용해야 합니다.
스팟 Main객체에 프로그램의 내부 파일에 값을 저장하고 가져오는 함수가 제공되고 있습니다.
Main.SetUserValue(sName, sValue)
Main.GetUserValue(sName)
Main.SetUserValue함수가 이름(sName)을 지정해 특정값(sValue)을 저장하는 함수이고
프로그램 설치 경우의 Spot폴더 안에 UserValue.yuv 파일에 해당 값이 저장됩니다.
Main.GetUserValue함수가 이름(sName)을 지정해 값을 다시 가져오는 함수입니다.
내부파일에는 JSON형태로 값저장도 가능합니다.
UserValue.yuv 파일에 지정한 이름으로 저장되므로
여러 전략식에서 Main.SetUserValue를 사용할 경우
서로 이름이 겹치지 않게 주의하시기 바랍니다.
아래 예제는 해당 함수를 이용하는 예제입니다.
1.
전략내용
종목검색으로 매수하고 특정 %로 익절, 손절, 트레일링스탑을 감시해 매도합니다.
익절과 손절은 현재가와 계좌 잔고의 평단가만 있으면
감시가 가능하므로별도로 값을 저장할 필요는 없지만
트레일링스탑은 매수 이후의 최고가를 계산해야 하는데
변수가 프로그램이 종료되면 값을 기억하지 못하기 때문에
별도로 저장하지 않으면 다음날에 연속적으로 사용이 가능하지 않습니다.
그러므로 각 종목별 진입 이후 최고가를 스팟 종료시 마다 내부파일에 적고
이후 스팟 시작 시에 불러와 해당 값으로 셋팅하고 최고가 갱신을 추적하게 됩니다.
2.
스크립트 객체화면 설정
a.
계좌객체
계좌객체를 추가한 후
속성에서 객체명은 Account1로 지정하고 주문 낼 계좌번호를 지정합니다.
3.
스팟수식
var 종목검색주기 = 30; //초
var 매도체크주기 = 5; //초
var UserSearchName = "사용자검색조건명";
var 매수금 = 500000;
var 최대매수종목수 = 20;
var 익절 = 30;//%
var 손절 = 10;//%
var 최소수익 = 20, 수익감소 = 10;//%
var ReqMKList = [];
var MKList = [];
var BuyList = [], HHList = [];
var stp,req;
//스팟 시작
function Main_OnStart()
{
Main.MessageList("Spot Start");
//내부파일에 적어 놓은 값들 가져와 저장
if (Main.GetUserValue("B") != "")
{
BuyList = JSON.parse(Main.GetUserValue("B"));
HHList = JSON.parse(Main.GetUserValue("H"));
}
ReqMKList = [];
if (BuyList.length > 0)
{
for (var i = BuyList.length-1; i >= 0 ; i--)
{
Account1.SetBalance(BuyList[i], 0);
//리스트중 계좌에 보유하지 않는 종목은 제거
if (Account1.Balance.count == 0)
{
BuyList.splice(i, 1);
HHList.splice(i, 1);
}
}
ReqMKList = BuyList;
Main.MessageList(ReqMKList);
}
MKList =[];
if (ReqMKList.length == 0)
{
Main.SetTimer(1, 종목검색주기*1000);
Main.SetTimer(3, 매도체크주기*1000);
stp = 1;
}
else
{
stp = 0;
req = 0;
Main.ReqMarketData(ReqMKList[req]);
Main.MessageList(req,"종목객체요청",ReqMKList[req]);
}
}
function Main_OnTimer(nEventID)
{
var d = new Date();
YYYYMMDD = d.getFullYear()*10000+(d.getMonth()+1)*100+d.getDate();
HHMMSS = d.getHours()*10000+d.getMinutes()*100+d.getSeconds();
if (nEventID == 1 && HHMMSS > 090000 && HHMMSS < 150000)
{
//타이머 종료
Main.KillTimer(1);
//지정한 이름의 사용자조건검색을 실행
Main.ReqPowerSearch(UserSearchName);
}
if (nEventID == 2)
{
Main.KillTimer(2);
//재요청
Main.ReqMarketData(ReqMKList[req]);
Main.MessageList(req,"종목객체 재요청",ReqMKList[req]);
}
if (nEventID == 3 && MKList.length > 0)
{
for (var i = 0; i < MKList.length; i++)
{
if (MKList[i].current > HHList[i] )
{
HHList[i] = MKList[i].current;
}
Account1.SetBalance(MKList[i].code, 0);
if (Account1.Balance.count == 0)
{
BuyList.splice(i, 1);
HHList.splice(i, 1);
}
else
{
if (MKList[i].current >= Account1.Balance.avgUnitCost*(1+익절/100))
{
Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,MKList[i].Bid(5),0);
Main.MessageList("익절매도",Account1.Balance.code);
//매도했으므로 리스트에서 삭제
BuyList.splice(i, 1);
HHList.splice(i, 1);
}
if (MKList[i].current <= Account1.Balance.avgUnitCost*(1-손절/100))
{
Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,MKList[i].Bid(5),0);
Main.MessageList("손절매도",Account1.Balance.code);
//매도했으므로 리스트에서 삭제
BuyList.splice(i, 1);
HHList.splice(i, 1);
}
if (HHList[i] > 0 &&
HHList[i] > Account1.Balance.avgUnitCost*(1+최소수익/100) &&
MKList[i].current < HHList[i]*(1-수익감소/100))
{
Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,MKList[i].Bid(5),0);
Main.MessageList("트레일링스탑매도",Account1.Balance.code);
//매도했으므로 리스트에서 삭제
BuyList.splice(i, 1);
HHList.splice(i, 1);
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount, aValues)
{
Main.KillTimer(1);
ReqMKList = [];
if (nCount >= 1)
{
if (MKList.length == 0)
{
//검색된 종목 중 잔고에 없는 종목으로 최대20개만 ReqMKList에 저장
for (var a = 0; a < nCount; a++)
{
Account1.SetBalance(aItemList[a],0);
if (Account1.Balance.count == 0 && ReqMKList.length < 최대매수종목수)
{
ReqMKList.push(aItemList[a]);
}
}
}
else
{
for (var a = 0; a < nCount; a++)
{
var Add = true;
for (var b = 0; b < MKList.length; b++)
{
if (aItemList[a] == MKList[b].code)
{
Add = false;
}
}
Account1.SetBalance(aItemList[a],0);
if (Account1.Balance.count > 0)
{
Add = false;
}
//종목객체로 만들어 지지 않았고 잔고에 없는 종목으로 선정하여
//요청리스트에 저장
if (Add == true && ReqMKList.length < 최대매수종목수-MKList.length)
{
ReqMKList.push(aItemList[a]);
}
}
}
}
Main.MessageList("종목객체요청할종목수:",ReqMKList.length);
if (ReqMKList.length == 0)
{
Main.SetTimer(1, 종목검색주기*1000);
}
else
{
req = 0;
Main.ReqMarketData(ReqMKList[req]);
Main.MessageList(req,"종목객체요청",ReqMKList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
//스팟시작 후 userfile에 있는 종목에 대한 종목객체요청
if (stp == 0)
{
if (MarketData.code == ReqMKList[req])
{
MKList.push(MarketData);
Main.MessageList(req,"종목객체생성",MarketData.code);
req = req+1;
if (req < ReqMKList.length)
{
var aa = Main.ReqMarketData(ReqMKList[req]);
if (aa == -1)
{
Main.SetTimer(2, 15000);
}
}
else
{
SC = 1;
Main.SetTimer(1, 종목검색주기*1000);
Main.SetTimer(3, 매도체크주기*1000);
}
}
}
else //종목검색 후 종목객체요청
{
if (MarketData.code == ReqMKList[req])
{
Main.MessageList(req,"종목객체생성",MarketData.code);
//종목객체 순차적으로 저장
MKList.push(MarketData);
//종목코드 순차적으로 저장
BuyList.push(MarketData.code);
//최고가 순차적으로 저장
HHList.push(MarketData.current);
//매수금만큼 매도1호가로 매수
var OP = MarketData.Ask(1);
var Vol = Math.floor(매수금/OP);
if (Vol > 0)
{
Account1.OrderBuy(MarketData.code,Vol,OP,0);
Main.MessageList("매수:",MarketData.code,Vol,OP);
}
else
{
Main.MessageList("금액부족으로 매수실행 안함");
}
req = req+1;
if (req < ReqMKList.length)
{
var aa = Main.ReqMarketData(ReqMKList[req]);
Main.MessageList(req,"종목객체요청",ReqMKList[req]);
if (aa == -1)
{
Main.MessageList(req,"생성제한",ReqMKList[req]);
Main.SetTimer(2, 15000);
}
}
else
{
Main.SetTimer(1, 종목검색주기*1000);
}
}
}
}
//스팟 종료시
function Main_OnClose()
{
//내부파일에 매수종목코드와 매도종목코드를 JSON형태로 저장
Main.SetUserValue("B",JSON.stringify(BuyList));
Main.SetUserValue("H",JSON.stringify(HHList));
}
JavaScript
복사