매입금액
—
보유 기준
평가금액
조회 중...
평가손익
—
평가금액 − 매입금액
수익률
—
평가손익 / 매입금액
총 분배금
—
— 건
분배율
—
분배금 / 입금액
복리 예상
설정에서 목표 연도 등을 지정하세요
목표 연도
—
—
예상 평가액
—
현재 계좌 총액 기준
예상 이자 누적
—
—
전체 거래내역
| 거래일자 | 구분 | 원본거래종류 | 종목코드 | 종목명 | 수량 | 단가 | 거래금액 | 수수료 |
|---|---|---|---|---|---|---|---|---|
|
⚙ 설정에서 구글 스프레드시트를 연동하면 데이터가 표시됩니다 |
||||||||
0 건
거래 추가
엑셀 업로드
증권사 거래내역 엑셀을 업로드하면 자동 파싱됩니다
엑셀 파일을 드래그하거나 클릭해서 업로드
.xlsx 형식 지원 (증권사 거래내역 원본)
📌 업로드 방법: 증권사 앱/HTS → 거래내역 → 엑셀 다운로드 → 여기에 업로드
📌 파싱 후 구글 스프레드시트에 자동으로 추가됩니다
📌 중복 거래일자는 자동으로 건너뜁니다
📌 파싱 후 구글 스프레드시트에 자동으로 추가됩니다
📌 중복 거래일자는 자동으로 건너뜁니다
수기 거래 입력
단건 입력은 아래 폼을 사용하세요
포트폴리오
| 종목명 | 종목코드 | 보유수량 | 매입평균단가 | 총매수금액 | 총분배금 | 현재가 | 전일가 | 전일대비 | 등락률 | 평가금액 | 평가손익 | 수익률 | 분배수익률 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
데이터를 불러오는 중... | |||||||||||||
현금예수금
—
분배금 내역
총 분배금 수령
—
수령 건수
—
분배금/입금 수익률
—
| 수령일자 | 종목코드 | 종목명 | 수령금액 | 누적합계 | 연도 |
|---|---|---|---|---|---|
데이터를 불러오는 중... | |||||
입금 내역
총 입금액
—
— 건
이체입금 (외부)
—
— 건
계좌대체입금 (내부)
—
— 건
| 입금일자 | 거래종류 | 입금금액 | 누적입금 | 연도 |
|---|---|---|---|---|
데이터를 불러오는 중... | ||||
계산기
최종 평가액
—
총 납입 원금
—
누적 이자
—
연도별 누적
| 연차 | 시작 잔액 | 납입 | 이자 | 종료 잔액 |
|---|---|---|---|---|
입력값을 넣으면 계산됩니다 | ||||
설정
복리 예상 설정 (개인연금 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);
}
}