Beancount 및 Fava를 사용한 스크립팅 가능한 워크플로우
Beancount (plain-text 복식 부기 회계 도구) 및 Fava (웹 인터페이스)는 확장 가능하고 스크립팅 가능합니다. 이를 통해 Python 스크립트를 작성하여 재무 작업을 자동화하고, 사용자 정의 보고서를 생성하고, 알림을 설정할 수 있습니다. 한 사용자의 말에 따르면 "데이터를 편리한 형식으로 가지고 있고, 원하는 대로 자동화할 수 있다는 점이 마음에 듭니다. 디스크에 있는 파일과 같은 API가 없으며, 통합하기 쉽습니다." 이 가이드에서는 초보자에게 적합한 자동화부터 고급 Fava 플러그인까지 스크립팅 가능한 워크플로우를 만드는 방법을 안내합니다.
시작하기: Python 스크립트로 Beancount 실행하기
)
특정 작업을 시작하기 전에 Beancount가 설치되어 있는지 확인하십시오 (예: pip install beancount
를 통해). Beancount는 Python으로 작성되었으므로 사용자 고유의 스크립트에서 라이브러리로 사용할 수 있습니다. 일반적인 접근 방식은 다음과 같습니다.
-
Beancount 원장 로드: Beancount 로더를 사용하여
.beancount
파일을 Python 객체로 파싱합니다. 예:from beancount import loader
entries, errors, options_map = loader.load_file("myledger.beancount")
if errors:
print("Errors:", errors)이렇게 하면
entries
(거래, 잔액 등) 목록과 메타데이터가 포함된options_map
이 제공됩니다. 이제 코드에서 모든 계정, 거래 및 잔액에 액세스할 수 있습니다. -
Beancount Query Language (BQL) 활용: 수동으로 반복하는 대신 데이터에 대해 SQL과 유사한 쿼리를 실행할 수 있습니다. 예를 들어 월별 총 지출을 얻으려면 쿼리 API를 사용할 수 있습니다.
from beancount.query import query
q = query.Query(entries, options_map)
result = q.query("SELECT month, sum(position) WHERE account ~ 'Expenses' GROUP BY month")
print(result)이것은 Beancount의 Query 시스템을 사용하여 데이터를 집계합니다. (내부적으로는
bean-query
명령이 수행하는 것과 유사하지만 여기서는 스크립트에서 사용하고 있습니다.) 실제로 Beancount 작성자는 파일을 로드하고 Python API를 통해 직접run_query()
를 호출하여 루프에서 외부 명령을 호출할 필요가 없다고 언급합니다. -
프로젝트 구조 설정: 원장과 함께 스크립트를 구성합니다. 일반적인 레이아웃은 임포터 (외부 데이터를 가져오고 파싱), 보고서 또는 쿼리 (분석 스크립트) 및 문서 (다운로드한 명세서를 저장)를 위한 디렉토리를 갖는 것입니다. 예를 들어 한 사용자는 다음을 유지합니다.
importers/
– 사용자 정의 Python 가져오기 스크립트 (테스트 포함),queries/
– 보고서를 생성하는 스크립트 (python3 queries/...
를 통해 실행 가능),documents/
– 계정별로 구성된 다운로드된 은행 CSV/PDF.
이 설정을 사용하면 스크립트를 수동으로 실행하거나 (예: python3 queries/cash_flow.py
) cron 또는 작업 실행기를 통해 스크립트를 예약하여 워크플로우를 자동화할 수 있습니다.
조정 작업 자동화
조정은 원장이 외부 기록 (은행 명세서, 신용 카드 보고서 등)과 일치하는지 확인하는 것을 의미합니다. Beancount의 plain-text 원장 및 Python API를 통해 이 프로세스의 상당 부분을 자동화할 수 있습니다.
거래 가져오기 및 매칭 (초급)
초보자의 경우 Beancount의 임포터 플러그인을 사용하는 것이 좋습니다. 주어진 형식 (CSV, OFX, PDF 등)을 파싱하고 거래를 생성하기 위해 Beancount의 임포터 프로토콜을 따르는 작은 Python 클래스를 작성합니다. 그런 다음 bean-extract
명령 또는 스크립트를 사용하여 이러한 임포터를 적용합니다.
- 은행의 CSV 형식에 대한 임포터 (예:
identify()
,extract()
와 같은 메서드가 있는 Python 클래스)를 작성합니다. Beancount의 설명서는 가이드 및 예제를 제공합니다. - 스크립트 또는 Makefile (예:
justfile
예제)에서bean-extract
를 사용하여 새 명세서를 파싱합니다. 예를 들어 한 워크플로우는~/Downloads
의 모든 파일에서bean-extract
를 실행하고 임시 파일에 거래를 출력합니다. - 임시 파일에서 거래를 수동으로 검토하고 기본 원장에 복사한 다음
bean-check
를 실행하여 잔액이 조정되었는지 확인합니다.
이 프로세스에는 여전히 검토 단계가 포함되지만 항목 파싱 및 형식 지정에 대한 대부분의 힘든 작업이 자동화됩니다. 임포터 스크립트는 카테고리를 자동 할당하고 불일치를 잡기 위해 잔액 어설션 (예상 잔액에 대한 설명)을 설정할 수도 있습니다. 예를 들어 가져온 후 2025-04-30 balance Assets:Bank:Checking 1234.56 USD
와 같은 줄이 있을 수 있으며 이는 마감 잔액을 어설션합니다. bean-check
를 실행하면 Beancount는 이러한 모든 잔액 어설션이 올바른지 확인하고 거래가 누락되거나 중복된 경우 오류를 플래그합니다. 이것은 모범 사례입니다. 각 명세서 기간에 대한 잔액 어설션을 자동 생성하여 컴퓨터가 조정되지 않은 차이점을 찾아내도록 합니다.
사용자 정의 조정 스크립트 (중급)
더 많은 제어를 위해 은행의 거래 목록 (CSV 또는 API를 통해)을 원장 항목과 비교하는 사용자 정의 Python 스크립트를 작성할 수 있습니다.
- 외부 데이터 읽기: Python의
csv
모듈 (또는 Pandas)을 사용하여 은행의 CSV 파일을 파싱합니다. 데이터를 날짜, 금액 및 설명이 포함된 거래 목록으로 정규화합니다. - 원장 거래 로드: 앞에서와 같이
loader.load_file
을 사용하여 모든 원장 항목을 가져옵니다. 이 목록을 관심 계정 (예: 당좌 예금 계정) 및 명세서의 날짜 범위로 필터링합니다. - 비교 및 불일치 찾기:
- 각 외부 거래에 대해 원장에 동일한 항목이 있는지 확인합니다 (날짜 및 금액, 아마도 설명으로 일치). 찾을 수 없으면 "새로움"으로 표시하고 검토할 수 있도록 Beancount 형식 거래로 출력합니다.
- 반대로 해당 계정에 외부 소스에 나타나지 않는 원장 항목을 식별합니다. 이는 데이터 입력 오류 또는 은행에서 정리되지 않은 거래일 수 있습니다.
- 결과 출력: 보고서를 인쇄하거나 누락된 거래가 포함된 새
.beancount
스니펫을 만듭니다.
예를 들어 **reconcile.py
**라는 커뮤니티 스크립트는 정 확히 이 작업을 수행합니다. Beancount 파일과 입력 CSV가 주어지면 가져와야 하는 새 거래 목록과 입력에 없는 기존 원장 게시 (잠재적으로 잘못된 분류의 신호)를 인쇄합니다. 이러한 스크립트를 사용하면 월별 조정은 스크립트를 실행한 다음 제안된 거래를 원장에 추가하는 것만큼 간단할 수 있습니다. 한 Beancount 사용자는 _"매달 모든 계정에 대해 조정 프로세스를 수행합니다."_라고 언급하고 Python 코드 모음을 늘려 데이터를 가져오고 조정하는 데 있어 대부분의 수동 작업을 제거합니다.
팁: 조정하는 동안 정확성을 위해 Beancount의 도구를 활용하십시오.
- 계정 잔액에 대한 자동 검사를 수행하기 위해 언급된 잔액 어설션을 사용합니다.
- 원하는 경우 사소한 반올림 차이에 대한 균형 조정 항목을 자동 삽입할 수 있는
pad
지시문을 사용합니다 (주의해서 사용하십시오). - 임포터 또는 조정 논리에 대한 단위 테스트를 작성합니다 (Beancount는 테스트 도우미를 제공합니다). 예를 들어 한 워크플로우는 샘플 CSV를 가져와 예상 거래로 실패하는 테스트를 작성한 다음 모든 테스트가 통과될 때까지 임포터를 구현하는 것을 포함했습니다. 이렇게 하면 가져오기 스크립트가 다양한 경우에 대해 올바르게 작동합니다.
사용자 정의 보고서 및 요약 생성
Fava는 많은 표준 보고서 (손익 계산서, 대차 대조표 등)를 제공하지만 스크립트를 사용하여 사용자 정의 보고서를 만들 수 있습니다. 이것은 간단한 콘솔 출력에서 풍부한 형식 파일 또는 차트에 이르기까지 다양합니다.
보고서를 위한 데이터 쿼리 (초급)
기본 수준에서는 Beancount Query Language (BQL)를 사용하여 요약 데이터를 가져와 인쇄하거나 저장할 수 있습니다. 예를 들어:
-
현금 흐름 요약: 쿼리를 사용하여 순 현금 흐름을 계산합니다. "현금 흐름"은 일정 기간 동안 특정 계정의 잔액 변화로 정의될 수 있습니다. BQL을 사용하여 다음과 같이 할 수 있습니다.
SELECT year, month, sum(amount)
WHERE account LIKE 'Income:%' OR account LIKE 'Expenses:%'
GROUP BY year, month이렇게 하면 모든 수입 및 지출 게시물이 월별로 정산됩니다. 이것을
bean-query
CLI 또는 Python API (query.Query
(앞에서와 같이))를 통해 실행한 다음 결과를 형식화할 수 있습니다. -
카테고리별 지출 보고서: 카테고리별 총 지출을 쿼리합니다.
SELECT account, round(sum(position), 2)
WHERE account ~ 'Expenses'
GROUP BY account
ORDER BY sum(position) ASC이렇게 하면 카테고리별 지출 표가 생성됩니다. 스크립트에서 여러 쿼리를 실행하고 결과를 텍스트, CSV 또는 추가 처리를 위해 JSON으로 출력할 수 있습니다.
한 사용자는 **Fava 또는 스크립트를 사용하여 재무 데이터를 분석하는 것이 "사소하다"**는 것을 발견하고, Python 스크립트 하나를 사용하여 Query Language를 통해 Beancount에서 데이터를 가져와 Pandas DataFrame에 넣어 사용자 정의 보고서를 준비한다고 언급했습니다. 예를 들어 쿼리를 사용하여 월별 합계를 가져온 다음 Pandas/Matplotlib를 사용하여 시간 경과에 따른 현금 흐름 차트를 플롯할 수 있습니다. BQL과 데이터 과학 라이브러리의 조합을 사용하면 Fava에서 기본적으로 제공하는 것 이상으로 보고서를 작성할 수 있습니다.
고급 보고 (차트, 성과 등)
보다 고급적인 요구 사항의 경우 스크립트를 사용하여 투자 성과와 같은 메트릭을 계산하거나 시각적 출력을 만들 수 있습니다.
-
투자 성과 (IRR/XIRR): 원장에는 모든 현금 흐름 (매수, 매도, 배당금)이 포함되어 있으므로 포트폴리오 수익률을 계산할 수 있습니다. 예를 들어 투자 계정의 거래를 필터링한 다음 내부 수익률을 계산하는 스크립트를 작성할 수 있습니다. 현금 흐름 데이터가 주어지면 IRR을 계산하는 라이브러리 (또는 공식)가 있습니다. 일부 커뮤니 티에서 개발한 Fava 확장 프로그램 (PortfolioSummary 또는 fava_investor와 같은)은 정확히 이 작업을 수행하여 투자 포트폴리오에 대한 IRR 및 기타 메트릭을 계산합니다. 스크립트로서 일련의 기여/인출 플러스 종료 값에 대해 IRR 함수 (NumPy 또는 사용자 고유의)를 사용할 수 있습니다.
-
다중 기간 또는 사용자 정의 메트릭: 매월 저축률 (소득 대비 저축 비율) 보고서를 원하십니까? Python 스크립트는 원장을 로드하고, 모든 수입 계정과 모든 지출 계정을 합산한 다음, 저축 = 수입 - 지출 및 백분율을 계산할 수 있습니다. 이것은 멋진 표를 출력하거나 기록을 위해 HTML/Markdown 보고서를 생성할 수도 있습니다.
-
시각화: Fava 외부에서 차트를 생성할 수 있습니다. 예를 들어 스크립트에서
matplotlib
또는altair
를 사용하여 원장 데이터를 사용하여 시간 경과에 따른 순자산 차트를 만듭니다. 원장에 모든 과거 잔액이 있거나 항목을 반복하여 누적할 수 있으므로 시계열 플롯을 생성할 수 있습니다. 이러한 차트를 이미지 또는 대화형 HTML로 저장합니다. (앱 내 시각적 개체를 선호하는 경우 아래의 Fava 확장 섹션을 참조하여 Fava 내에서 차트를 추가하십시오.)
출력 옵션: 보고서를 제공하는 방법을 결정합니다.
- 일회성 분석의 경우 화면에 인쇄하거나 CSV/Excel 파일에 저장하는 것으로 충분할 수 있습니다.
- 대시보드의 경우 데이터를 포함하는 HTML 파일 (Jinja2와 같은 템플릿 라이브러리를 사용하거나 Markdown을 작성)을 생성하여 브라우저에서 열 수 있습니다.
- 대화형 보고 환경을 위해 Jupyter Notebook과 통합할 수도 있지만 이는 자동화보다 탐색에 더 적합합니다.
원장에서 알림 트리거
스크립팅 가능한 워크플로우의 또 다른 강력한 용도는 재무 데이터의 조건에 따라 알림을 설정하는 것입니다. 원장이 정기적으로 업데이트되므로 (다가오는 청구서 또는 예산과 같은 미래 날짜 항목을 포함할 수 있음) 스크립트로 스캔하여 중요한 이벤트에 대한 알림을 받을 수 있습니다.
낮은 계정 잔액 경고
초과 인출을 피하거나 최소 잔액을 유지하려면 계정 (예: 당좌 예금 또는 저축)이 임계값 아래로 떨어지면 알림을 받기를 원할 수 있습니다. 다음은 이를 구현하는 방법입니다.
-
현재 잔액 확인: 로더를 통해
entries
를 로드한 후 관심 있는 계정의 최신 잔액을 계산합니다. 게시물을 집계하거나 쿼리를 사용하여 이 작업을 수행할 수 있습니다. 예를 들어 특정 계정의 잔액에 대한 BQL 쿼리를 사용합니다.SELECT sum(position) WHERE account = 'Assets:Bank:Checking'
이렇게 하면 해당 계정의 현재 잔액 (모든 게시물의 합계)이 반환됩니다. 또는 Beancount의 내부 함수를 사용하여 대차 대조표를 작성합니다. 예를 들어:
from beancount.core import realization
tree = realization.realize(entries, options_map)
acct = realization.get_or_create(tree, "Assets:Bank:Checking")
balance = acct.balance # an Inventory of commodities그런 다음 숫자 값을 추출합니다 (예:
balance.get_currency_units('USD')
는 Decimal을 제공할 수 있음). 그러나 대부분의 경우 쿼리를 사용하는 것이 더 간단합니다. -
임계값 확인: 잔액을 미리 정의된 제한과 비교합니다. 아래에 있으면 알림을 트리거합니다.
-
알림 트리거: 이것은 콘솔에 경고를 인쇄하는 것만큼 간단할 수 있지만 실제 알림의 경우 이메일 또는 푸시 알림을 보낼 수 있습니다. 이메일 (
smtplib
를 통해) 또는 IFTTT 또는 Slack의 웹후크 API와 같은 서비스와 통합하여 알림을 푸시할 수 있 습니다. 예를 들어:if balance < 1000:
send_email("Low balance alert", f"Account XYZ balance is {balance}")(
send_email
을 이메일 서버 세부 정보로 구현합니다.)
이 스크립트를 매일 (cron 작업 또는 Windows 작업 스케줄러를 통해) 실행하면 사전 예방적 경고를 받게 됩니다. 원장을 사용하고 있으므로 방금 추가한 항목을 포함하여 모든 거래를 고려할 수 있습니다.
다가오는 결제 기한
Beancount를 사용하여 청구서 또는 기한을 추적하는 경우 미래 결제를 표시하고 스크립트를 통해 알림을 받을 수 있습니다. Beancount에서 다가오는 의무를 나타내는 두 가지 방법은 다음과 같습니다.
-
이벤트: Beancount는 임의의 날짜 메모에 대한
event
지시문을 지원합니다. 예를 들어:2025-05-10 event "BillDue" "Mortgage payment due"
이것은 잔액에 영향을 미치지는 않지만 레이블이 있는 날짜를 기록합니다. 스크립트는
Event.type == "BillDue"
(또는 선택한 사용자 정의 유형)인Event
항목에 대해entries
를 스캔하고 날짜가 오늘부터 다음 7일 이내에 있는지 확인할 수 있습니다. 예인 경우 알림 (이메일, 알림 또는 팝업까지)을 트리거합니다. -
미래 거래: 일부 사람들은 예약된 결제와 같은 것에 대해 미래 날짜 거래 (사후 날짜)를 입력합니다. 이러한 항목은 날짜가 지날 때까지 잔액에 표시되지 않습니다 (미래 날짜 현재의 보고서를 실행하지 않는 한). 스크립트는 가까운 미래에 날짜가 지정된 거래를 찾아서 나열할 수 있습니다.
이러한 항목을 사용하여 실행 시 곧 만기가 되는 작업 또는 청구서 목록을 출력하는 "틱커" 스크립트를 만들 수 있습니다. Google 캘린더 또는 작업 관리자와 같은 API와 통합하여 알림을 자동으로 만들려면 여기에서 만드십시오.
이상 감지
알려진 임계값 또는 날짜를 넘어 비정상적인 패턴에 대한 사용자 정의 알림을 스크립팅할 수 있습니다. 예를 들어 일반적으로 월별 지출이 발생하지 않았거나 (청구서 지불을 잊었을 수 있음) 이번 달에 카테고리 지출이 비정상적으로 높은 경우 스크립트가 플래그를 지정할 수 있습니다. 일반적으로 최근 데이터를 쿼리하고 기록과 비교하는 것이 포함됩니다 (고급 주제일 수 있음 – 통계 또는 ML을 사용할 수 있음).
실제로 많은 사용자는 조정을 통해 이상 (예상치 못한 거래)을 포착합니다. 은행 알림 (각 거래에 대한 이메일과 같은)을 받으면 스크립트로 파싱하고 Beancount에 자동으로 추가하거나 적어도 기록되었는지 확인할 수 있습니다. 한 매니아는 거래 알림 이메일을 보내도록 은행을 구성하여 원장에 자동으로 파싱하고 추가할 계획까지 세웠습니다. 이러한 종류의 이벤트 기반 알림은 기록되지 않은 거래가 없는지 확인할 수 있습니다.
사용자 정의 플러그인 및 뷰를 사용하여 Fava 확장
Fava는 확장 시스템을 통해 이미 스크립팅할 수 있습니다. 자동화 또는 보고서를 웹 인터페이스에 직접 통합하려는 경우 Python으로 Fava 확장 (플러그인이라고도 함)을 작성할 수 있습니다.
Fava 확장이 작동하는 방식: 확장은 fava.ext.FavaExtensionBase
에서 상속되는 클래스를 정의하는 Python 모듈입니다. 사용자 정의 옵션을 통해 Beancount 파일에 등록합니다. 예를 들어 MyAlerts(FavaExtensionBase)
클래스가 있는 myextension.py
파일이 있는 경우 원장에 다음을 추가하여 활성화할 수 있습니다.
1970-01-01 custom "fava-extension" "myextension"
Fava가 로드되면 해당 모듈을 가져와 MyAlerts
클래스를 초기화합니다.
확장은 여러 가지 작업을 수행할 수 있습니다.
- 후크: Fava 수명 주기의 이벤트에 연결할 수 있습니다. 예를 들어
after_load_file()
은 원장이 로드된 후에 호출됩니다. 이것을 사용하여 검사를 실행하거나 데이터를 미리 계산할 수 있습니다. Fava 내에서 낮은 잔액 검사를 구현하려는 경우after_load_file
은 계정 잔액을 반복하고 경고를 저장할 수 있습니다 (UI에 표시하려면 FavaAPIError를 발생시키거나 Javascript를 사용하여 알림을 표시하는 것과 같이 약간 더 많은 작업이 필요할 수 있지만). - 사용자 정의 보고서/페이지: 확장 클래스가
report_title
속성을 설정하면 Fava는 사이드바에 새 페이지를 추가합니다. 그런 다음 해당 페이지의 콘텐츠에 대한 템플릿 (HTML/Jinja2)을 제공합니다. 이것은 Fava에 기본적으로 없는 대시보드 또는 요약과 같은 완전히 새로운 뷰를 만드는 방법입니다. 확장은 필요한 모든 데이터를 수집하고 (모든 항목, 잔액 등이 있는self.ledger
에 액세스할 수 있음) 템플릿을 렌더링할 수 있습니다.
예를 들어 Fava의 내장 portfolio_list
확장은 포트폴리오 포지션을 나열하는 페이지를 추가합니다. 커뮤니티 확장은 더 나아갑니다.
- 대시보드: fava-dashboards 플러그인을 사용하면 사용자 정의 차트 및 패널 (Apache ECharts와 같은 라이브러리 사용)을 정의할 수 있습니다. 실행할 쿼리의 YAML 구성을 읽고 Beancount를 통해 실행하고 Fava에 동적 대시보드 페이지를 생성합니다. 본질적으로 Beancount 데이터와 JavaScript 차트 라이브러리를 연결하여 대화형 시각화를 생성합니다.
- 포트폴리오 분석: PortfolioSummary 확장 (사용자 제공)은 투자 요약 (계정 그룹화, IRR 계산 등)을 계산하고 Fava UI에 표시합니다.
- 거래 검토: 또 다른 확장인 fava-review는 시간이 지남에 따라 거래를 검토하는 데 도움이 됩니다 (예: 영수증을 놓치지 않았는지 확인).
간단한 확장을 직접 만들려면 FavaExtensionBase
를 서브클래싱하여 시작합니다. 예를 들어 페이지를 추가하는 최소한의 확장은 다음과 같습니다.
from fava.ext import FavaExtensionBase
class HelloReport(FavaExtensionBase):
report_title = "Hello World"
def __init__(self, ledger, config):
super().__init__(ledger, config)
# any initialization, perhaps parse config if provided
def after_load_file(self):
# (optional) run after ledger is loaded
print("Ledger loaded with", len(self.ledger.entries), "entries")
이것을 hello.py
에 넣고 원장에 custom "fava-extension" "hello"
를 추가하면 Fava에 새 "Hello World" 페이지가 표시됩니다 (확장이 후크만 사용하는 경우가 아니면 페이지 콘텐츠를 정의하기 위해 templates
하위 폴더에 템플릿 파일 HelloReport.html
도 필요합니다). 템플릿은 확장 클래스에 첨부하는 데이터를 사용할 수 있습니다. Fava는 Jinja2 템플릿을 사용하므로 해당 템플릿에서 데이터를 HTML 표 또는 차트로 렌더링할 수 있습니다.
참고: Fava의 확장 시스템은 강력하지만 "불안정" (변경될 수 있음)으로 간주됩니다. 사용자 정의 페이지를 만드는 경우 웹 개발 (HTML/JS)에 대한 지식이 필요합니다. 스크립트 또는 분석을 실행하는 것이 목표라면 외부 스크립트로 유지하는 것이 더 쉬울 수 있습니다. 워크플로우에 대한 맞춤형 앱 내 경험을 원하는 경우 Fava 확장을 사용하십시오.
타사 API 및 데이터 통합
스크립팅 가능한 워크플로우의 장점 중 하나는 외부 데이터를 가져올 수 있다는 것입니다. 다음은 일반적인 통합입니다.
-
환율 및 상품: Beancount는 보고서를 결정적으로 유지하기 위해 자동으로 가격을 가져오지 않지만 가격을 제공할 수 있도록 Price 지시문을 제공합니다. 이러한 가격을 가져오는 것을 자동화할 수 있습니다. 예를 들어 스크립트는 API (Yahoo Finance, Alpha Vantage 등)를 쿼리하여 최신 환율 또는 주가를 가져와 가격 항목을 원장에 추가할 수 있습니다.
2025-04-30 price BTC 30000 USD
2025-04-30 price EUR 1.10 USDBeancount 형식으로 매일 견적을 가져와 출력하는
bean-price
(현재 beancount의 우산 아래에 있는 외부 도구)와 같은 도구가 있습니다. 매일 밤bean-price
를 실행하도록 예약하여prices.beancount
포함 파일을 업데이트할 수 있습니다. 또는 Python을 사용하십시오. 예를 들어requests
라이브러리를 사용하여 API를 호출합니다. Beancount의 설명서는 공개적으로 거래되는 자산의 경우 "가격을 다운로드하 고 지시문을 작성하는 코드를 호출할 수 있다"고 제안합니다. 즉, 스크립트가 조회를 수행하고price
줄을 삽입하도록 하십시오. 수동으로 수행하는 것보다 좋습니다. -
주식 포트폴리오 데이터: 환율과 유사하게 API와 통합하여 자세한 주식 데이터 또는 배당금을 가져올 수 있습니다. 예를 들어 Yahoo Finance API (또는
yfinance
와 같은 커뮤니티 라이브러리)는 티커에 대한 과거 데이터를 검색할 수 있습니다. 스크립트는 소유한 각 주식에 대한 월별 가격 기록으로 원장을 업데이트하여 시장 가치에 대한 정확한 과거 보고서를 활성화할 수 있습니다. 일부 사용자 정의 확장 (예: fava_investor)은 표시를 위해 즉석에서 가격 데이터를 가져오지만 가장 간단한 방법은 가격을 정기적으로 원장에 가져오는 것입니다. -
뱅킹 API (오픈 뱅킹/Plaid): CSV를 다운로드하는 대신 API를 사용하여 거래를 자동으로 가져올 수 있습니다. Plaid와 같은 서비스는 은행 계좌를 집계하고 거래에 대한 프로그래밍 방식 액세스를 허용합니다. 고급 설정에서는 Plaid의 API를 사용하여 매일 새 거래를 가져와 파일에 저장 (또는 원장에 직접 가져오기)하는 Python 스크립트를 가질 수 있습니다. 한 파워 유저는 Plaid가 자신의 가져오기 파이프라인에 공급되는 시스템을 구축하여 자신의 장부를 거의 자동화했습니다. 그들은 "Plaid API에 가입하고 로컬에서 동일한 작업을 수행하는 것을 막을 수 있는 것은 없다"고 언급합니다. 즉, 은행 데이터를 가져오는 로컬 스크립트를 작성한 다음 Beancount 임포터 논리를 사용하여 원장 항목으로 파싱할 수 있습니다. 일부 지역에는 은행에서 제공하는 오픈 뱅킹 API가 있습니다. 그것들은 비슷하게 사용될 수 있습니다.
-
기타 API: 예산 책정 도구를 통합하거나 (계획된 예산을 내보내 Beancount의 실제와 비교) OCR API를 사용하여 영수증을 읽고 거래와 자동으로 일치시킬 수 있습니다. 스크립트가 Python의 에코시스템에 대한 모든 액세스 권한을 가지므로 이메일 서비스 (알림 전송용)에서 Google Sheets (예: 월별 재무 메트릭으로 시트 업데이트)에 이르기까지 모든 것을 메시징 앱 (Telegram 봇을 통해 요약 보고서를 자신에게 보냄)에 통합할 수 있습니다.
타사 API를 사용할 때는 자격 증명을 보호하고 (API 키에 환경 변수 또는 구성 파일 사용) 스크립트에서 오류 (네트워크 문제, API 가동 중지 시간)를 정상적으로 처리하십시오. 데이터를 캐시하는 것이 종종 현명합니다 (예: 가져온 환율을 저장하여 동일한 과거 환율을 반복적으로 요청하지 않음).
모듈식, 유지 관리 가능한 스크립트를 위한 모범 사례
스크립팅 가능한 워크플로우를 구축할 때 코드를 체계적이고 강력하게 유지하십시오.
-
모듈성: 서로 다른 우려 사항을 서로 다른 스크립트 또는 모듈로 분할합니다. 예를 들어 "데이터 가져오기/조정"과 "보고서 생성"과 "알림"에 대한 별도의 스크립트를 가집니 다.
ledger_import.py
,ledger_reports.py
등과 같은 모듈을 사용하여 원장에 대한 작은 Python 패키지를 만들 수도 있습니다. 이렇게 하면 각 부분을 더 쉽게 이해하고 테스트할 수 있습니다. -
구성: 값을 하드 코딩하지 마십시오. 계정 이름, 임계값, API 키, 날짜 범위 등과 같은 항목에 대해 구성 파일 또는 스크립트 맨 위에 있는 변수를 사용하십시오. 이렇게 하면 코드를 깊이 편집하지 않고도 쉽게 조정할 수 있습니다. 예를 들어 맨 위에
LOW_BALANCE_THRESHOLDS = {"Assets:Bank:Checking": 500, "Assets:Savings": 1000}
을 정의하면 알림 스크립트가 이 dict를 반복할 수 있습니다. -
테스트: 재무 자동화를 미션 크리티컬 코드로 취급하십시오. 복잡한 논리에 대한 테스트를 작성하십시오. Beancount는 원장 입력을 시뮬레이션하는 데 활용할 수 있는 일부 테스트 도우미 (임포터 테스트에 내부적으로 사용됨)를 제공합니다. 멋진 프레임워크가 없어도 더미 CSV와 예상 출력 거래를 가질 수 있으며 가져오기 스크립트가 올바른 항목을 생성한다고 주장할 수 있습니다.
pytest
를 사용하는 경우 이러한 테스트를 쉽게 통합할 수 있습니다 (Alex Watt가 pytest를 래핑하는just test
명령을 통해 수행한 것처럼). -
버전 제어: 원장과 스크립트를 버전 제어 (git) 하에 유지하십시오. 이렇게 하면 백업 및 기록이 제공될 뿐만 아니라 제어된 방식으로 변경하는 것이 좋습니다. "재무 스크립트"의 릴리스를 태그하거나 문제를 디버깅할 때 차이점을 검토할 수 있습니다. 일부 사용자는 시간이 지남에 따른 변경 사항을 확인하기 위해 Git에서 재무 기록을 추적하기도 합니다. 리포지토리에서 민감한 데이터 (원시 명세서 파일 또는 API 키와 같은)를 무시하십시오.
-
설명서: 나중에 사용할 수 있도록 사용자 정의 워크플로우를 문서화하십시오. 환경을 설정하는 방법, 각 스크립트를 실행하는 방법, 각 스크립트가 수행하는 작업을 설명하는 리포지토리의 README는 몇 달이 지나면 매우 귀중할 것입니다. 또한 코드, 특히 명확하지 않은 회계 논리 또는 API 상호 작용을 주석으로 처리합니다.
-
Fava 플러그인 유지 관리: Fava 확장을 작성하는 경우 간단하게 유지하십시오. Fava가 변경될 수 있으므로 대상 기능이 있는 더 작은 확장을 업데이트하는 것이 더 쉽습니다. 원장 변경에 민감할 수 있는 하드 코딩 계산보다 Beancount의 쿼리 엔진 또는 기존 도우미 함수를 최대한 활용하십시오.
-
보안: 스크립트가 민감한 데이터를 처리하고 외부 서비스에 연결할 수 있으므로 주의해서 다루십시오. API 키를 노출하지 말고 안전한 컴퓨터에서 자동화를 실행하는 것을 고려하십시오. 호스팅된 솔루션 또는 클라우드 (GitHub Actions를 예약하거나 Fava를 실행하는 서버와 같은)를 사용하는 경우 원장 데이터가 저장 시 암호화되고 개인 정보 보호에 만족하는지 확인하십시오.
이러한 관행을 따르면 재정이 (그리고 도구 자체도) 발전함에 따라 워크플로우가 안정적으로 유지됩니다. 최소한의 조정으로 해마다 재사용할 수 있는 스크립트를 원합니다.
결론
Beancount와 Fava는 기술에 정통한 사용자가 개인 재무 추적을 완전히 사용자 정의할 수 있는 강력하고 유연한 플랫폼을 제공합니다. Python 스크립트를 작성하여 명세서 조정과 같은 지루한 작업을 자동화하고, 요구 사항에 맞는 풍부한 보고서를 생성하고,시기 적절한 알림으로 재정을 최신 상태로 유지할 수 있습니다. 기본 쿼리 및 CSV 가져오기부터 시작하여 완전한 Fava 플러그인 및 외부 API 통합으로 이동하는 기본에서 고급에 이르기까지 다양한 예제를 다루었습니다. 이를 구현할 때 간단하게 시작하여 점진적으로 구축하십시오. 몇 가지 작은 자동화 스크립트만으로도 시간과 노력을 절약하고 정확성을 크게 향상시킬 수 있습니다. 그리고 모든 것이 plain text와 Python이기 때문에 완전히 제어할 수 있습니다. 재무 시스템은 사용자와 함께 성장하고 특정 요구 사항에 맞춰집니다. 즐거운 스크립팅 되세요!
출처: 위의 기술은 Beancount 설명서 및 커뮤니티 경험에서 가져온 것입니다. 자세한 내용은 Beancount의 공식 문서, 커뮤니티 가이드 및 블로그, 유용한 플러그인 및 도구에 대한 링크는 Awesome Beancount 리포지토리를 참조하십시오.