گردشکارهای اسکریپتپذیر با Beancount و Fava
Beancount (یک ابزار حسابداری دوطرفه متن ساده) و Fava (رابط وب آن) بسیار توسعهپذیر و اسکریپتپذیر هستند. طراحی آنها به شما این امکان را میدهد که با نوشتن اسکریپتهای پایتون، وظایف مالی را خودکار کنید، گزارشهای سفارشی تولید کنید و هشدارهایی را تنظیم کنید. به گفته یکی از کاربران، "من واقعاً از داشتن دادههایم در چنین قالب مناسبی لذت میبرم و دوست دارم که بتوانم همه چیز را مطابق میل خودکار کنم. هیچ API مانند یک فایل روی دیسک شما وجود ندارد؛ ادغام با آن آسان است." این راهنما شما را در ایجاد گردشکارهای اسکریپتپذیر راهنمایی میکند - از اتوماسیون مبتدیپسند تا افزونههای پیشرفته Fava.
شروع به کار: اجرای Beancount به عنوان یک اسکریپت پایتون
قبل از پرداختن به وظایف خاص، مطمئن شوید که Beancount را نصب کردهاید (به عنوان مثال از طریق pip install beancount). از آنجا که Beancount به زبان پایتون نوشته شده است، میتوانید از آن به عنوان یک کتابخانه در اسکریپتهای خود استفاده کنید. رویکرد کلی به این صورت است:
-
بارگیری دفتر کل Beancount خود: از لودر Beancount برای تجزیه فایل
.beancountبه اشیاء پایتون استفاده کنید. به عنوان مثال:from beancount import loader
entries, errors, options_map = loader.load_file("myledger.beancount")
if errors:
print("Errors:", errors)این یک لیست از
entries(تراکنشها، موجودیها و غیره) و یکoptions_mapبا فرادادهها به شما میدهد. اکنون همه حسابها، تراکنشها و موجودیهای شما در کد قابل دسترسی هستند. -
بهرهگیری از زبان پرس و جو Beancount (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 برای جمعآوری دادهها استفاده میکند. (در پشت صحنه، این شبیه به کاری است که دستور
bean-queryانجام میدهد، اما در اینجا شما از آن در یک اسکریپت استفاده میکنید.) در واقع، نویسنده Beancount اشاره میکند که میتوانید فایل را بارگیری کرده وrun_query()را مستقیماً از طریق API پایتون فراخوانی کنید و از نیاز به فراخوانی دستورات خارجی در یک حلقه جلوگیری کنید. -
تنظیم ساختار پروژه: اسکریپتهای خود را در کنار دفتر کل خود سازماندهی کنید. یک طرحبندی رایج این است که دایرکتوریهایی برای واردکنندهها (برای واکشی/تجزیه دادههای خارجی)، گزارشها یا پرس و جوها (برای اسکریپتهای تجزیه و تحلیل) و اسناد (برای ذخیره صورتحسابهای دانلود شده) داشته باشید. به عنوان مثال، یک کاربر موارد زیر را نگهداری میکند:
importers/- اسکریپتهای واردات پایتون سفارشی (با تستها)،queries/- اسکریپتهایی برای تولید گزارشها (قابل اجرا از طریقpython3 queries/...)،documents/- فایلهای CSV/PDF دانلود شده بانکی که بر اساس حساب سازماندهی شدهاند.
با این تنظیمات، میتوانید اسکریپتها را به صورت دستی اجرا کنید (به عنوان مثال python3 queries/cash_flow.py) یا آنها را زمانبندی کنید (از طریق cron یا یک task runner) تا گردش کار خود را خودکار کنید.
خودکارسازی وظایف تطبیق
تطبیق به معنای اطمینان از مطابقت دفتر کل شما با سوابق خارجی (صورتحسابهای بانکی، گزارشهای کارت اعتباری و غیره) است. دفتر کل متن ساده و API پایتون Beancount، خودکارسازی بسیاری از این فرآیند را ممکن میسازد.
وارد کردن و تطبیق تراکنشها (مبتدی)
برای مبتدیان، رویکرد توصیه شده استفاده از افزونههای واردکننده Beancount است. شما یک کلاس پایتون کوچک را مطابق با پروتکل واردکننده Beancount مینویسید تا یک قالب معین (CSV، OFX، PDF و غیره) را تجزیه کرده و تراکنشها را تولید کند. سپس از دستور bean-extract یا یک اسکریپت برای اعمال این واردکنندهها استفاده کنید:
- یک واردکننده بنویسید (یک کلاس پایتون با متدهایی مانند
identify()،extract()) برای فرمت CSV بانک خود. مستندات Beancount یک راهنما و مثالهایی را ارائه میدهد. - از
bean-extractدر یک اسکریپت یا Makefile (مانند مثالjustfile) برای تجزیه صورتحسابهای جدید استفاده کنید. برای مثال، یک گردش کارbean-extractرا روی همه فایلهای موجود در~/Downloadsاجرا میکند و تراکنشها را در یک فایل موقت خروجی میدهد. - تراکنشها را به صورت دستی بررسی و از فایل موق ت در دفتر کل اصلی خود کپی کنید، سپس
bean-checkرا اجرا کنید تا مطمئن شوید که موجودیها تطبیق میشوند.
در حالی که این فرآیند هنوز شامل یک مرحله بررسی است، بسیاری از کارهای سنگین تجزیه و قالببندی ورودیها خودکار میشوند. اسکریپتهای واردکننده همچنین میتوانند به طور خودکار دستهها را اختصاص دهند و حتی ادعاهای موجودی (اظهارات موجودیهای مورد انتظار) را برای تشخیص مغایرتها تنظیم کنند. برای مثال، پس از وارد کردن، ممکن است خطی مانند 2025-04-30 balance Assets:Bank:Checking 1234.56 USD داشته باشید که موجودی پایانی را ادعا میکند. هنگامی که bean-check را اجرا میکنید، Beancount تأیید میکند که همه این ادعاهای موجودی صحیح هستند و در صورت گم شدن یا تکراری بودن تراکنشها، هر گونه خطایی را علامتگذاری میکند. این یک بهترین روش است: ادعاهای موجودی را به طور خودکار برای هر دوره صورتحساب تولید کنید تا به رایانه اجازه دهید تفاوتهای تطبیق نشده را برای شما تشخیص دهد.
اسکریپتهای تطبیق سفارشی (متوسط)
برای کنترل بیشتر، میتوانید یک اسکریپت پایتون سفارشی بنویسید تا لیست تراکنشهای یک بانک (CSV یا از طریق API) را با ورودیهای دفتر کل خود مقایسه کنید:
- خواندن دادههای خارجی: فایل CSV بانک را با استفاده از ماژول
csvپایتون (یا Pandas) تجزیه کنید. دادهها را به یک لیست از تراکنشها نرمال کنید، به عنوان مثال هر کدام با تاریخ، مبلغ و توضیحات. - بارگیری تراکنشهای دفتر کل: از
loader.load_fileهمانطور که قبلاً نشان داده شد برای دریافت همه ورودیهای دفتر کل استفاده کنید. این لیست را به حساب مورد نظر فیلتر کنید (به عنوان مثال حساب جاری شما) و شاید محدوده تاریخ صورتحساب. - مقایسه و یافتن عدم تطابق:
- برای هر تراکنش خارجی، بررسی کنید که آیا یک ورودی یکسان در دفتر کل وجود دارد (مطابقت بر اساس تاریخ و مبلغ، شاید توضیحات). اگر یافت نشد، آن را به عنوان "جدید" علامتگذاری کنید و احتمالاً آن را به عنوان یک تراکنش با فرمت Beancount برای بررسی شما خروجی دهید.
- برعکس، هر ورودی دفتر کل را در آن حساب شناسایی کنید که در منبع خارجی ظاهر نمیشود - اینها میتوانند خطاهای ورود داده یا تراکنشهایی باشند که بانک آنها را تسویه نکرده است.
- خروجی نتایج: یک گزارش چاپ کنید یا یک قطعه
.beancountجدید با تراکنشهای از دست رفته ایجاد کنید.
به عنوان مثال، یک اسکریپت انجمن به نام reconcile.py دقیقاً این کار را انجام میدهد: با توجه به یک فایل Beancount و یک ورودی CSV، لیستی از تراکنشهای جدید را که باید وارد شوند، چاپ میکند، و همچنین هر گونه ثبت دفتر کل موجود که در ورودی نیستند (به طور بالقوه نشانه طبقهبندی اشتباه). با چنین اسکریپتی، تطبیق ماهانه میتواند به آسانی اجرای آن و سپس پیوست کردن تراکنشهای پیشنهادی به دفتر کل شما باشد. یکی از کاربران Beancount اشاره میکند که "هر ماه یک فرآیند تطبیق را روی همه حسابها انجام میدهند" و از یک مجموعه رو به رشد از کد پایتون برای حذف بسیاری از کارهای دستی در وارد کردن و تطبیق دادهها استفاده میکنند.
نکته: در طول تطبیق، از ابزارهای Beancount برای دقت استفاده کنید:
- همانطور که ذکر شد، از ادعاهای موجودی برای بررسی خودکار موجودی حسابها استفاده کنید.
- در صورت تمایل از دستور
padاستفاده کنید، که میتواند به طور خودکار ورودیهای تعادلی را برای تفاوتهای جزئی گرد کردن وارد کند (با احتیاط استفاده کنید). - برای منطق واردکننده یا تطبیق خود تست واحد بنویسید (Beancount کمککنندههای تست را ارائه میدهد). برای مثال، یک گردش کار شامل گرفتن یک CSV نمونه، نوشتن تستهای ناموفق با تراکنشهای مورد انتظار، و سپس پیادهسازی واردکننده تا زمانی که همه تستها قبول شوند. این تضمین میکند که اسکریپت واردات شما به درستی برای موارد مختلف کار میکند.
تولید گزارشها و خلاصههای سفارشی
در حالی که Fava بسیاری از گزارشهای استاندارد (صورت سود و زیان، ترازنامه و غیره) را ارائه میدهد، میتوانید با استفاده از اسکریپتها گزارشهای سفارشی ایجاد کنید. اینها میتوانند از خروجیهای کنسول ساده تا فایلها یا نمودارهای قالببندی شده غنی متغیر باشند.
پرس و جو از دادهها برای گزارشها (مبتدی)
در سطح ابتدایی، میتوانید از زبان پرس و جو Beancount (BQL) برای دریافت دادههای خلاصه و چاپ یا ذخیره آن استفاده کنید. برای مثال:
-
خلاصه جریان نقدی: از یک پرس و جو برای محاسبه خالص جریان نقدی استفاده کنید. "جریان نقدی" میتواند به عنوان تغییر در موجودی حسابهای خاص در یک دوره تعریف شود. با استفاده از BQL، میتوانید این کار را انجام دهید:
SELECT year, month, sum(amount)
WHERE account LIKE 'Income:%' OR account LIKE 'Expenses:%'
GROUP BY year, monthاین تمام ثبتهای درآمد و هزینه را بر اساس ماه خالص میکند. میتوانید این را از طریق CLI
bean-queryیا از طریق API پایتون (query.Queryهمانطور که قبلاً نشان داده شد) اجرا کنید و سپس نتیجه را قالببندی کنید. -
گزارش هزینههای دستهبندی: کل هزینهها را بر اساس دستهبندی پرس و جو کنید:
SELECT account, round(sum(position), 2)
WHERE account ~ 'Expenses'
GROUP BY account
ORDER BY sum(position) ASCاین یک جدول از هزینهها بر اساس دستهبندی را به دست میدهد. میتوانید چندین پرس و جو را در یک اسکریپت اجرا کنید و نتایج را به صورت متن، CSV یا حتی JSON برای پردازش بیشتر خروجی دهید.
یک کاربر متوجه شد که تجزیه و تحلیل دادههای مالی با Fava یا با اسکریپتها "بدیهی" است، و اشاره کرد که آنها از یک اسکریپت پایتون برای بیرون کشیدن دادهها از Beancount از طریق زبان پرس و جو و سپس قرار دادن آن در یک DataFrame پاندا برای تهیه یک گزارش سفارشی استفاده میکنند. برای مثال، ممکن است مجموع ماهانه را با یک پرس و جو واکشی کنید و سپس از Pandas/Matplotlib برای رسم نمودار جریان نقدی در طول زمان استفاده کنید. ترکیب BQL و کتابخانههای علم داده به شما این امکان را میدهد که گزارشهایی فراتر از آنچه Fava به طور پیش فرض ارائه میدهد، بسازید.
گزارشدهی پیشرفته (نمودارها، عملکرد و غیره)
برای نیازهای پیشرفتهتر، اسکریپتهای شما میتوانند معیارهایی مانند عملکرد سرمایهگذاری را محاسبه کنند یا خروجیهای بصری ایجاد کنند:
-
عملکرد سرمایهگذاری (IRR/XIRR): از آنجا که دفتر کل شما شامل تمام جریانهای نقدی (خرید، فروش، سود سهام) است، میتوانید نرخ بازده پورتفولیو را محاسبه کنید. برای مثال، میتوانید اسکریپتی بنویسید که تراکنشهای حسابهای سرمایهگذاری شما را فیلتر کرده و سپس نرخ بازده داخلی را محاسبه کند. کتابخانهها (یا فرمولهایی) برای محاسبه IRR با توجه به دادههای جریان نقدی وجود دارد. برخی از افزونههای Fava توسعهیافته توسط انجمن (مانند PortfolioSummary یا fava_investor) دقیقاً این کار را انجام میدهند و IRR و سایر معیارها را برای پورتفولیوهای سرمایهگذاری محاسبه میکنند. به عنوان یک اسکریپت، میتوانید از یک تابع IRR (از NumPy یا خودتان) در سری مشارکتها/برداشتها به اضافه مقدار پایانی استفاده کنید.
-
معیارهای چند دورهای یا سفارشی: آیا یک گزارش از نرخ پسانداز (نسبت پسانداز به درآمد) خود در هر ماه میخواهید؟ یک اسکریپت پایتون میتواند دفتر کل را بارگیری کند، تمام حسابهای درآمد و تمام حسابهای هزینه را جمع کند، سپس پسانداز = درآمد - هزینهها و درصد را محاسبه کند. این میتواند یک جدول زیبا را خروجی دهد یا حتی یک گزارش HTML/Markdown برای سوابق شما تولید کند.
-
تصویرسازی: میتوانید نمودارها را در خارج از Fava تولید کنید. برای مثال، از
matplotlibیاaltairدر یک اسکریپت برای ایجاد نمودار ارزش خالص در طول زمان با استفاده از دادههای دفتر کل استفاده کنید. از آنجا که دفتر کل دارای تمام موجودیهای تاریخی است (یا میتوانید با تکرار ورودیها آنها را جمعآوری کنید)، میتوانید نمودارهای سری زمانی را تولید کنید. این نمودارها را به عنوان تصاویر یا HTML تعاملی ذخیره کنید. (اگر تصاویر درون برنامهای را ترجیح میدهید، برای افزودن نمودارها درون Fava، بخش افزونه Fava را در زیر ببینید.)
گزینههای خروجی: تصمیم بگیرید که چگونه گزارش را ارائه دهید:
- برای تجزیه و تحلیل یکباره، چاپ روی صفحه یا ذخیره در یک فایل CSV/Excel ممکن است کافی باشد.
- برای داشبوردها، ایجاد یک فایل HTML با دادهها (احتمالاً با استفاده از یک کتابخانه الگو مانند Jinja2 یا حتی فقط نوشتن Markdown) که میتوانید در یک مرورگر باز کنید، در نظر بگیرید.
- همچنین میتوانید با Jupyter Notebooks برای یک محیط گزارشدهی تعاملی ادغام شوید، اگرچه این بیشتر برای کاوش است تا اتوماسیون.