커뮤니티
예스스팟 관련해서
안녕하세요.
일전에 도움을 받아서 매도 조건를 수정 했었는 데 손실이 너무 커서아래와 같이 매도를 수정 하려고 합니다.
1. 이익보존 3.5 % 에 익절 하기전에 3분봉 기준 볼린저밴드(a,a)상한선 이탈 하지 않았으면 익절 하지 않고 보류 하고 있다가 볼린저밴드( a,a )상한선 이탈 하면 익절 합니다.
이익보존 3. 5%에 도달 했을 때 3분봉 기준 볼린저밴드(a,a)상한선 이탈 했으면 익절 합니다.
2 이익실현 7%이 익절 하기전 3분봉 기준 볼린저밴드(a,a) 상한선 이탈 하지 않았으면 익절 하지 않고 있다가 3분봉 기준 볼린저밴드( a,a) 상한선 이탈하면 익절한다.
이익실현 7%에 도달 했을 때 3분봉 기준 볼린저밴드(a,a) 상한선 이탈 했으면 익절한다.
AI 도움으로 아래와 같이 만들었는 데, 수고스럽지만 확인 좀 부탁 드립니다.
늘 수고 해주심에 머리 숙여 감사함을 전 합니다.
var timer5 = 5; // 5초 간격 종목검색
var 매수금 = 50000;
var OrderList = [];
var MKList = [];
var ChartList = []; // 3분봉 차트 객체 저장 배열
var req;
// 매도 조건 설정
var SELL_GAIN = 7.0; // 이익실현 기준 7%
var SELL_BREAK = 3.5; // 이익보존 기준 3.5%
var SELL_LOSS = -2.0; // 손절 -2%
// 볼린저밴드 변수
var BB_PERIOD = a; // 볼린저밴드 기간
var BB_D = a; // 볼린저밴드 승수
function Main_OnStart()
{
// 1번 타이머: 종목 검색용 (5초)
Main.SetTimer(1, timer5 * 1000);
// 3번 타이머: 실시간 잔고 수익률 감시용 (2초마다 체크)
Main.SetTimer(3, 2000);
MKList = [];
ChartList = [];
Main.MessageList("자동매매 시작 (익절/보존: 볼린저밴드 3분 a,a 연동)");
// 기존 계좌에 있는 종목들에 대해서도 3분봉 차트를 요청
var num = Account1.GetTheNumberOfBalances();
for (var i = 0; i < num; i++) {
Account1.SetBalanceIndex(i);
RequestChartEx(Account1.Balance.code);
}
}
function Main_OnTimer(nEventID)
{
var d = new Date();
var HHMMSS = d.getHours()*10000 + d.getMinutes()*100 + d.getSeconds();
// 1. 매수 종목 검색 (09:00 ~ 15:20)
if (nEventID == 1 && HHMMSS > 090000 && HHMMSS < 152000)
{
Main.ReqPowerSearch("기본전략");
}
// 2. 종목 객체 요청 지연 처리
if (nEventID == 2)
{
Main.KillTimer(2);
Main.ReqMarketData(OrderList[req]);
}
// 3. 매도 감시 로직 (수익률 + 볼린저밴드 체크)
if (nEventID == 3)
{
var num = Account1.GetTheNumberOfBalances();
for (var i = 0; i < num; i++)
{
Account1.SetBalanceIndex(i);
var code = Account1.Balance.code;
var currentRate = (Account1.Balance.current / Account1.Balance.avgUnitCost - 1) * 100;
var currentPrice = Account1.Balance.current;
// 손절 처리 (볼밴 무관하게 -2% 도달 시 즉시 매도)
if (currentRate <= SELL_LOSS)
{
Account1.OrderSell(code, Account1.Balance.count, 0, 1);
Main.MessageList("▼손절(-2%) 매도:", code, "수익률:", currentRate.toFixed(2));
continue; // 손절했으므로 다음 종목으로 넘어감
}
// 수익권(3.5% 이상)일 때 볼린저밴드 상한선 계산 및 이탈 확인
if (currentRate >= SELL_BREAK)
{
var myChart = GetChartObj(code); // 해당 종목의 3분봉 차트 객체 찾기
if (myChart != null && myChart.GetReqCount() >= BB_PERIOD)
{
// 볼린저밴드 상한선 계산 로직 (MA + D * StdDev)
var sum = 0;
for (var k = 0; k < BB_PERIOD; k++) {
sum += myChart.GetClose(1, k);
}
var ma = sum / BB_PERIOD;
var sumVar = 0;
for (var k = 0; k < BB_PERIOD; k++) {
var diff = myChart.GetClose(1, k) - ma;
sumVar += (diff * diff);
}
var stddev = Math.sqrt(sumVar / BB_PERIOD);
var bbUp = ma + (BB_D * stddev); // 볼린저밴드 상한선
// 이탈 조건: 현재가가 상한선 아래에 있을 때 매도
if (currentPrice < bbUp)
{
if (currentRate >= SELL_GAIN) {
Account1.OrderSell(code, Account1.Balance.count, 0, 1);
Main.MessageList("★이익실현(7%이상) 매도 - 상한선 이탈:", code, "수익률:", currentRate.toFixed(2));
}
else if (currentRate >= SELL_BREAK && currentRate < SELL_GAIN) {
Account1.OrderSell(code, Account1.Balance.count, 0, 1);
Main.MessageList("●이익보존(3.5%이상) 매도 - 상한선 이탈:", code, "수익률:", currentRate.toFixed(2));
}
}
// 주가가 상한선보다 크거나 같으면 (currentPrice >= bbUp) 홀딩!
}
}
}
}
}
function Main_OnRcvItemList(aItemList, nCount)
{
Main.KillTimer(1);
OrderList = [];
if (nCount >= 1)
{
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]);
}
}
}
if (OrderList.length == 0) {
Main.SetTimer(1, timer5 * 1000);
} else {
req = 0;
Main.ReqMarketData(OrderList[req]);
}
}
function Main_OnRcvMarketData(MarketData)
{
if (MarketData.code == OrderList[req])
{
MKList.push(MarketData);
if (!IsStockInAccount(MarketData.code))
{
// 매수 주문 실행
Account1.OrderBuy(MarketData.code, Math.floor(매수금 / MarketData.Ask(1)), 0, 1);
Main.MessageList(MarketData.code + " 매수 수행");
// 매수와 동시에 3분봉 차트 객체 요청 (볼밴 감시용)
RequestChartEx(MarketData.code);
}
req = req + 1;
if (req < OrderList.length)
{
var aa = Main.ReqMarketData(OrderList[req]);
if (aa == -1) Main.SetTimer(2, 15000);
}
else
{
Main.SetTimer(1, timer5 * 1000);
}
}
}
// ---------------------- 차트 객체 관련 함수 ---------------------- //
// 3분봉 차트 요청 함수
function RequestChartEx(code) {
// 중복 요청 방지
for (var i = 0; i < ChartList.length; i++) {
if (ChartList[i].GetCode(1) == code) return;
}
// ReqChartItem(종목코드, 주기, 주기구분, 조회건수, 조회건수구분, 수정주가여부, 갭보정여부)
var reqChart = new ReqChartItem(code, 3, CHART_PERIOD_MINUTE, 50, CHART_REQCOUNT_BAR, false, false);
Main.ReqChartEx(reqChart);
}
// 요청한 차트 객체 수신 시 배열에 저장
function Main_OnRcvChartEx(ChartEx)
{
ChartList.push(ChartEx);
}
// 배열에서 특정 종목의 차트 객체 찾기
function GetChartObj(code) {
for (var i = 0; i < ChartList.length; i++) {
if (ChartList[i].GetCode(1) == code) {
return ChartList[i];
}
}
return null;
}
// ----------------------------------------------------------------- //
function IsStockInAccount(stockCode) {
var numberOfBalances = Account1.GetTheNumberOfBalances();
for (var i = 0; i < numberOfBalances; i++) {
Account1.SetBalanceIndex(i);
if (stockCode == Account1.Balance.code) {
return true;
}
}
return false;
}
답변 2
예스스탁 예스스탁 답변
2026-05-21 14:36:06
victor
2026-05-22 09:51:04