답변완료
수식 추가 수정 부탁드립니다.
안녕하세요.
매번 예스스탁의 커뮤니티를 이용하여 많은 내용들을 배우고 또 질문에 성의 껏 답변해 주심에 감사드립니다.
질문하나 드립니다.
예스스팟에서 아래 스팟 수식을 이용하여 예스랭귀지로 만든 수식으로 파워종목을 만들어 자동 매수하고, 미리 일괄적으로 정해 둔 적절한 수익률과 손절률을 'STOP 주문설정' 창에 셋팅하여 자동 매도를 하고 있는데, 모든 종목의 스텐스가 달라 일정비율의 매도는 비효율적이어서 익과 손절을 적절히 못하고 있습니다.
그래서 파워종목으로 편집한 매도 조건을 포함하여 보유 종목을 대상으로 자동 매도를 하거나, 아니면 간단한 지표 몇가지를 스팟 수식에 추가 설정하여 자동 매도가 되게 만들고 싶습니다.
1. 매수한 보유종목 중 매도조건에 충족되면 자동 매도가 되도록 정하고 싶습니다.
예) 예스랭귀지로 매수[파일명 : MY_BB030]와 매도[파일명 : MY_SS123]의 조건을 편집해서 파워종목 식으로 자동 매수 매도되게 스팟수식을 만든다.
2. 몇 가지 지표들로 매도조건을 정하여 스팟 수식에 포함하여 자동매도 되도록 한다.
예) 특정 주기와 D값을 이용하여 그 볼린저밴드의 상단선을 상향돌파 또는 하향돌파하는 시점에 자동 매도 또는 종가가 5이평 하향돌파 시 자동 매도, 엔벨 상한선이 2일 연속 하락하고 종가가 시가보다 하락하면 자동 매도 등의 간단한 조건을 스팟 수식에 포함하여 자동매도한다.
3. 예스랭귀지와 파워종목 검색식으로 매도 조건의 수식을 만들어서 예스 스팟과 연동되게 하는 스팟에서 추가되는 부분에 대해서도 설명해주시면 고맙겠습니다.
4. 계좌별 보유종목에 적용하여 사용하고자 합니다. 위 1)번과 2)번 조건이 만족되면 자동 매도하는 것입니다.
부탁드립니다.
현재 사용하고 있는 예스스팟 매수매도 수식
--------------------
var M_Buy = 50000000;//종목당 1회 매수금액
var OPEN_T = 90000;
var CLOSE_T = 120000;
var SearchName = "MY_BB030"; //PowerSearch Name
var timer = 10; //매수 매도 초(시간) 간격
var Earning_Rate = 1.12; //계좌평가금액이 스팟시작시 평가금액대비 12% 이상이면 전종목 전량매도
var Trailing_Stop = 0.8; // 전량 손절
var Earning_Sale = 1.12; // 전량 익절
var OrderList = [];
var MKList = [];
var req;
function Main_OnStart()
{
//1번 타이머, "timer" 초
Main.SetTimer(1, timer*1000);
// 오늘 매수한 종목 관리 배열 초기화
MKList = [];
//스팟 시작시 잔고평가금액
V1 = Account1.GetBalanceETCinfo(100);
}
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 >= OPEN_T && HHMMSS < CLOSE_T)
{
//종목검색 수행
Main.ReqPowerSearch(SearchName)
Main.MessageList("ReqPowerSearch1");
}
if (nEventID == 1)
{
//계좌보유종수
var num = Account1.GetTheNumberOfBalances();
//9시~15시 15분 사이
if (HHMMSS >= 90000 && HHMMSS < 151500)
{
//보유종목이 1개 이상
if (num >= 1)
{
//계좌평가금액이 스팟시작시 평가금액대비 12% 이상이면 전종목 전량매도
if (Account1.GetBalanceETCinfo(100) >= V1*Earning_Rate)
{
//1번 타이머 종료
Main.KillTimer(1);
//계좌리스트의 순서대로
for (var i = 0; i < num; i++)
{
//잔고를 셋팅
Account1.SetBalance(i);
//수량이 있고 Earning_Rate(60%)수익이거나 손실이면 시장가 매도
if (Account1.Balance.count > 0)
{
Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1);
}
}
}
else //아니면 개별종목 30% Earning_Sale, -20% Trailing_Stop 체크
{
//계좌리스트의 순서대로
for (var i = 0; i < num; i++)
{
//잔고를 셋팅
Account1.SetBalance(i);
//수량이 있고 "Earning_Sale"수익이거나 "Trailing_Stop" 손실이면 시장가 매도
if (Account1.Balance.count > 0 &&
(Account1.Balance.current >= Account1.Balance.avgUnitCost*Earning_Sale ||
Account1.Balance.current <= Account1.Balance.avgUnitCost*Trailing_Stop))
{
Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1);
}
}
}
}
}
/* 15시 15분 이후이면 계좌의 모든 잔량 시장가 매도 관련 시스템[시작]
15시 15분 이후이면 계좌의 모든 잔량 시장가 매도 관련 시스템[시작]
if (HHMMSS >= 151500)
{
//1번 타이머 종료
Main.KillTimer(1);
//계좌리스트의 순서대로
for (var i = 0; i < num; i++)
{
//잔고를 셋팅
Account1.SetBalance(i);
//수량이 있고 5%수익이거나 5% 손실이면 시장가 매도
if (Account1.Balance.count > 0)
{
Account1.OrderSell(Account1.Balance.code,Account1.Balance.count,0,1);
}
}
}
15시 15분 이후이면 계좌의 모든 잔량 시장가 매도 관련 시스템[시작]
15시 15분 이후이면 계좌의 모든 잔량 시장가 매도 관련 시스템[시작]
*/
}
if (nEventID == 2)
{
Main.ReqMarketData(OrderList[req]);
Main.MessageList("ReqMarketData:",OrderList[req]); ;
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.KillTimer(1);
Main.MessageList("aItemList:",aItemList);
OrderList = [];
if (nCount >= 1)
{
if (MKList.length == 0)
{
OrderList = aItemList;
}
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;
}
}
if (Add == true && !IsStockInAccount(aItemList[a]))
{
OrderList.push(aItemList[a]);
}
}
}
}
Main.MessageList("OrderList:",OrderList);
if (OrderList.length == 0)
{
Main.SetTimer(1, timer*1000);
}
else
{
req = 0;
Main.ReqMarketData(OrderList[req]);
Main.MessageList("ReqMarketData:",OrderList[req]); ;
}
}
function Main_OnRcvMarketData(MarketData)
{
if (MarketData.code == OrderList[req])
{
MKList.push(MarketData);
// 계좌에 같은 종목이 있는지 확인
if (!IsStockInAccount(MarketData.code)) {
// 계좌에 없는 경우에만 매수
// Account1.OrderBuy(MarketData.code,1,0,1);
Account1.OrderBuy(MarketData.code,Math.floor(M_Buy/MarketData.Ask(1)),0,1);
// Account1.OrderBuy(MarketData.code,Math.floor(M_Buy/MarketData.Ask(1)),MarketData.Ask(1),0);
//지정가로 주문하고자 하시면 주문함수 내용을 위와 같이 변경하시면 됩니다.
Main.MessageList(MarketData.code + " 주식을 매수합니다.");
} else {
Main.MessageList( MarketData.code + " 주식은 이미 계좌에 있으므로 매수하지 않습니다.");
}
req = req+1;
if (req < OrderList.length)
{
var aa = Main.ReqMarketData(OrderList[req]);
Main.MessageList("ReqMarketData:",OrderList[req]); ;
if (aa == -1)
{
Main.SetTimer(2, 15000);
}
}
else
{
Main.SetTimer(1, timer*1000);
}
}
}
function IsStockInAccount(stockCode) {
// 계좌에 해당 종목이 있는지 확인하는 함수
var numberOfBalances = Account1.GetTheNumberOfBalances();
for (var i = 0; i < numberOfBalances; i++) {
Account1.SetBalance(i);
if (stockCode == Account1.Balance.code) {
return true; // 계좌에 같은 종목이 있으면 true 반환
}
}
return false; // 계좌에 같은 종목이 없으면 false 반환
}
감사합니다.
2024-07-15
710
글번호 226040
답변완료
도움 요청 드립니다.
## 검색종목이 보유종목 이고,
+/- 조건일 경우 불타기/물타기 하려 합니다.
여러 수식들을 참고해 조건 수식 작성했는데,나머지는 잘 동작하는데
이 부분만 오랜 시간 수정하며 작동 했는데 안되서 도움 요청 드립니다.
var Req;
var BL = [] ; // 보유종목 코드 저장 리스트
var MK = [], MKreq;
var MKCnt = [];
var MKItem = [];
//종목검색이 완료
function Main_OnRcvItemList(aItemList, nCount)
{
var num = Account1.GetTheNumberOfBalances();
//검색종목수가 1개 이상이면
if (nCount >= 1 )
{
ItemList = aItemList;
Count = nCount;
Main.MessageList("검색완료",ItemList);
//종목객체 생성 요청
Main.MessageList("요청전 EntryItem",EntryItem);
var include = false;
for (var i = 0; i < num.length; i++ )
{
//잔고를 셋팅
Account1.SetBalanceItem(i);
if ( Account1.Balance.code == ItemList[Req] ) // 검색종목이 보유종목
{
include = true;
}
}
if (include == true )
{
Account1.SetBalanceItem(ItemList[Req] ,0);
var cond = false;
for (var i = 0; i < MKItem.length; i++)
{
if (MKItem[i] == ItemList[Req])
{
cond = true;
}
}
if (MKCnt[i] == 0 && Account1.Balance.count > 0 )
{
Account1.SetBalance(MK[i].code, 0);
Vol1 = Math.floor(추가매수금액/MK[i].Bid(1));
if (cond == true && Account1.Balance.current <= Account1.Balance.avgUnitCost * 0.8 )
{
Main.MessageList(Account1.Balance.code,"|보유종목 -20% 이하 추가 물타기 매수 ");
MKCnt[i] = 1;
Account1.OrderBuy(MK[i].code, Vol1, MK[i].Ask(2), 0);
}
if (cond == true && Account1.Balance.current >= Account1.Balance.avgUnitCost * 1.05 )
{
Main.MessageList(Account1.Balance.code,"|보유종목 +5% 이상 추가 불타기 매수 ");
MKCnt[i] = 1;
Account1.OrderBuy(MK[i].code, Vol1,MK[i].Ask(2), 0);
}
}
}
if (include == false) // 검색종목이 보유종목 아님
{
Account1.SetBalanceItem(ItemList[Req] ,0);
var Entry = false;
for(var z = 0; z < EntryItem.length; z++)
{
if (EntryItem[z] == ItemList[Req])
{
Entry = true;
}
}
if (Entry == false )
{
if (Account1.Balance.count == 0)
{
Main.ReqMarketData(ItemList[Req], 0, 0);
Main.MessageList("요청",ItemList[Req],Req);
}
}
if (Entry == true)
{
Main.MessageList("요청x",ItemList[Req]);
}
}
Req = Req+1;
Main.SetTimer(2, 3000);//간격(4초)
}
else
{
Main.MessageList("검색종목 없어 3초후 재검색");
Search = false;
}
}
//요청한 종목객체가 생성되면
function Main_OnRcvMarketData(MarketData)
{
//요청한 종목객체 생성이 완료되면
if (MarketData.code == BL[MKreq])//a MK[MKreq] = MarketData 담기
{
Main.MessageList("종목객체생성 : ",MarketData.code);
//MK배열변수에 종목객체 저장
MK[MKreq] = MarketData;
MKItem[MKreq] = MarketData.code;
MKCnt[MKreq] = 0 ;
MKreq = MKreq+1;
if (MKreq < BL.length)
{
Main.MessageList("ReqMarket : ",MKreq,BL[MKreq]);
S = Main.ReqMarketData(BL[MKreq]);
if (S == -1)
{
Main.MessageList("종목객체 생성제한 : ", Main.GetLimitedTime(0));
Main.SetTimer(4, 16000);// 타이머 4 15초 이후 간격(16초)
}
}
else
{
Main.MessageList("BL종목객체요청완료");
}
}
2024-06-19
637
글번호 226037