매입금액
—
보유 기준
평가금액
조회 중...
평가손익
—
평가금액 − 매입금액
수익률
—
평가손익 / 매입금액
총 분배금
—
— 건
분배율
—
분배금 / 입금액
복리 예상
설정에서 목표 연도 등을 지정하세요
목표 연도
—
—
예상 평가액
—
현재 계좌 총액 기준
예상 이자 누적
—
—
전체 거래내역
| 거래일자 | 구분 | 원본거래종류 | 종목코드 | 종목명 | 수량 | 단가 | 거래금액 | 수수료 |
|---|---|---|---|---|---|---|---|---|
|
⚙ 설정에서 구글 스프레드시트를 연동하면 데이터가 표시됩니다 |
||||||||
0 건
거래 추가
엑셀 업로드
증권사 거래내역 엑셀을 업로드하면 자동 파싱됩니다
⚠ 주의 — 반드시 .xlsx로 변환 후 업로드
국내 HTS(카이로스·키움·대신·NH 등)에서 받은 CSV는 CP949 인코딩이라 Mac에서 바로 업로드하면 한글이 깨지고 컬럼이 어긋납니다.
엑셀(또는 Numbers)에서 열고 → 다른 이름으로 저장 → .xlsx 형식으로 변환한 뒤에만 업로드하세요.
국내 HTS(카이로스·키움·대신·NH 등)에서 받은 CSV는 CP949 인코딩이라 Mac에서 바로 업로드하면 한글이 깨지고 컬럼이 어긋납니다.
엑셀(또는 Numbers)에서 열고 → 다른 이름으로 저장 → .xlsx 형식으로 변환한 뒤에만 업로드하세요.
엑셀 파일을 드래그하거나 클릭해서 업로드
.xlsx 형식만 지원 (위 주의사항 필독)
📌 업로드 방법: 증권사 HTS → 거래내역 다운로드(보통 CSV) → Excel/Numbers에서 열기 → .xlsx로 저장 → 여기에 업로드
📌 파싱 후 Supabase에 자동으로 추가됩니다
📌 같은 파일을 두 번 업로드하면 중복이 생기니 조심하세요
📌 파싱 후 Supabase에 자동으로 추가됩니다
📌 같은 파일을 두 번 업로드하면 중복이 생기니 조심하세요
수기 거래 입력
단건 입력은 아래 폼을 사용하세요
포트폴리오
| 종목명 | 종목코드 | 보유수량 | 매입평균단가 | 총매수금액 | 총분배금 | 현재가 | 전일가 | 전일대비 | 등락률 | 평가금액 | 평가손익 | 수익률 | 분배수익률 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
데이터를 불러오는 중... | |||||||||||||
현금예수금
—
분배금 내역
총 분배금 수령
—
수령 건수
—
분배금/입금 수익률
—
| 수령일자 | 종목코드 | 종목명 | 수령금액 | 누적합계 | 연도 |
|---|---|---|---|---|---|
데이터를 불러오는 중... | |||||
입금 내역
총 입금액
—
— 건
이체입금 (외부)
—
— 건
계좌대체입금 (내부)
—
— 건
| 입금일자 | 거래종류 | 입금금액 | 누적입금 | 연도 |
|---|---|---|---|---|
데이터를 불러오는 중... | ||||
계산기
최종 평가액
—
총 납입 원금
—
누적 이자
—
연도별 누적
| 연차 | 시작 잔액 | 납입 | 이자 | 종료 잔액 |
|---|---|---|---|---|
입력값을 넣으면 계산됩니다 | ||||
설정
복리 예상 설정 (개인연금 1)
거래내역 하단에 목표 연도까지의 복리 예상이 표시됩니다
원금 기준: 현재 평가금액 + 현금예수금
구글 스프레드시트 연동
📋 연동 방법 (Google Apps Script)
1. 구글 스프레드시트 열기 → 확장 프로그램 → Apps Script
2. 아래 코드를 붙여넣고 저장
3. 배포 → 새 배포 → 유형: 웹앱 → 액세스: 모든 사용자
4. 생성된 URL을 위에 입력
1. 구글 스프레드시트 열기 → 확장 프로그램 → Apps Script
2. 아래 코드를 붙여넣고 저장
3. 배포 → 새 배포 → 유형: 웹앱 → 액세스: 모든 사용자
4. 생성된 URL을 위에 입력
function doGet(e) {
const sheet = SpreadsheetApp.getActiveSpreadsheet();
const action = e.parameter.action;
if (action === 'read') {
const sheetName = e.parameter.sheet || '전체거래내역';
const ws = sheet.getSheetByName(sheetName);
const data = ws.getDataRange().getValues();
return ContentService
.createTextOutput(JSON.stringify({ ok: true, data: data }))
.setMimeType(ContentService.MimeType.JSON);
}
if (action === 'prices') {
const codes = e.parameter.codes.split(',');
const prices = {};
codes.forEach(code => {
try {
const price = FinanceApp.getStockInfo(code).price;
prices[code] = price;
} catch(err) {
// GOOGLEFINANCE 함수로 조회
try {
const formula = '=GOOGLEFINANCE("' + code + '","price")';
const temp = sheet.getSheetByName('전체거래내역');
prices[code] = 0;
} catch(e2) {}
}
});
return ContentService
.createTextOutput(JSON.stringify({ ok: true, prices: prices }))
.setMimeType(ContentService.MimeType.JSON);
}
if (action === 'append') {
const sheetName = e.parameter.sheet || '전체거래내역';
const ws = sheet.getSheetByName(sheetName);
const row = JSON.parse(e.parameter.row);
ws.appendRow(row);
return ContentService
.createTextOutput(JSON.stringify({ ok: true }))
.setMimeType(ContentService.MimeType.JSON);
}
}
function doPost(e) {
const sheet = SpreadsheetApp.getActiveSpreadsheet();
const body = JSON.parse(e.postData.contents);
if (body.action === 'append_batch') {
const ws = sheet.getSheetByName(body.sheet || '전체거래내역');
body.rows.forEach(row => ws.appendRow(row));
return ContentService
.createTextOutput(JSON.stringify({ ok: true, added: body.rows.length }))
.setMimeType(ContentService.MimeType.JSON);
}
if (body.action === 'prices') {
const codes = body.codes;
const prices = {};
// 임시 셀에 GOOGLEFINANCE 수식으로 조회
const ws = sheet.getSheetByName('전체거래내역');
codes.forEach((code, i) => {
try {
const cell = ws.getRange(1000 + i, 20);
cell.setFormula('=GOOGLEFINANCE("' + code + '","price")');
SpreadsheetApp.flush();
prices[code] = cell.getValue();
cell.clear();
} catch(err) { prices[code] = 0; }
});
return ContentService
.createTextOutput(JSON.stringify({ ok: true, prices: prices }))
.setMimeType(ContentService.MimeType.JSON);
}
}