3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在A股市场中,**应收账款(Accounts Receivable)**过高往往是企业财务爆雷的前兆。如果一家企业的应收账款占总资产或营业收入的比例过高,可能意味着其销售回款困难、坏账风险极高,甚至存在虚增利润的嫌疑。
在 ptrade 量化交易平台中,我们可以利用 get_fundamentals 接口轻松获取上市公司的财务报表数据。本指南将教你如何提取资产负债表中的应收账款(account_receivable)与资产总计(total_assets),并计算其比例,从而在选股时剔除高风险股票。
要获取应收账款数据,我们需要调用 ptrade 的财务数据接口 get_fundamentals,定位到资产负债表(balance_statement)。
get_fundamentals(security, table, fields=None, date=None, start_year=None, end_year=None, report_types=None, date_type=None, merge_type=None)
['600570.SS', '000001.SZ']。'balance_statement'(资产负债表)。'account_receivable': 应收账款(单位:元)'total_assets': 资产总计(单位:元)'YYYYMMDD'。在回测中默认取当前回测交易日。以下是一个完整且可运行的 ptrade 策略示例。策略在盘前(before_trading_start)进行财务数据清洗与过滤,并在盘中对筛选出的安全股票进行买入操作。
import pandas as pd
import numpy as np
def initialize(context):
# 设置基准
set_benchmark('000300.SS')
# 设定操作的股票池(以沪深300成分股为例)
g.security_pool = get_index_stocks('000300.XBHS')
set_universe(g.security_pool)
# 风险控制阈值:应收账款占总资产比例不能超过 25%
g.max_ar_ratio = 0.25
# 筛选后的安全股票池
g.safe_stocks = []
def before_trading_start(context, data):
log.info("------ 盘前开始进行财务风险过滤 ------")
# 1. 获取当前交易日
current_date = context.blotter.current_dt.strftime('%Y%m%d')
# 2. 获取股票池的资产负债表数据
fields = ['account_receivable', 'total_assets']
try:
df_finance = get_fundamentals(security=g.security_pool,
table='balance_statement',
fields=fields,
date=current_date)
except Exception as e:
log.error("获取财务数据失败: %s" % e)
return
if df_finance is None or df_finance.empty:
log.warning("未获取到财务数据,保持原安全股票池")
return
# 3. 计算应收账款占比并过滤
g.safe_stocks = []
for stock in g.security_pool:
if stock in df_finance.index:
ar = df_finance.loc[stock, 'account_receivable']
assets = df_finance.loc[stock, 'total_assets']
# 排除数据缺失或总资产为负的异常情况
if pd.isna(ar) or pd.isna(assets) or assets <= 0:
continue
ar_ratio = ar / assets
# 过滤掉应收账款占比过高的股票
if ar_ratio < g.max_ar_ratio:
g.safe_stocks.append(stock)
else:
log.info("股票 %s 因应收账款占比过高 (%.2f%%) 被剔除" % (stock, ar_ratio * 100))
log.info("原始股票池数量: %d, 过滤后安全股票数量: %d" % (len(g.security_pool), len(g.safe_stocks)))
def handle_data(context, data):
# 简单交易逻辑:每日等权买入筛选出的前5只安全股票
if not g.safe_stocks:
return
target_list = g.safe_stocks[:5]
cash = context.portfolio.cash
if cash > 10000:
target_value = cash / len(target_list)
for stock in target_list:
if data[stock].is_open > 0:
order_value(stock, target_value)
log.info("买入安全财务标的: %s, 金额: %.2f" % (stock, target_value))
get_fundamentals 属于在线 HTTP 请求接口。ptrade 平台对其有流量限制(通常每秒不超过100次,单次最大调用量5万条数据)。在处理全A股等超大股票池时,建议在 before_trading_start 中一次性传入整个 list,避免在循环中单只股票重复调用。data[stock].is_open > 0 或 get_stock_status 检查股票是否处于停牌或退市整理期,防止废单。get_stock_blocks 进行同行业内部对比,效果更佳。