Skip to main content

fincanva

Build, backtest and analyse Fincanva strategies from Python, with your own Fincanva account.

pip install "fincanva[all]"     # with pandas and matplotlib; plain `fincanva` works without them
import matplotlib.pyplot as plt
import fincanva as fc

fc.connect()            # reads FINCANVA_API_KEY; never writes the key anywhere
fc.connect("fk_...")    # or the key itself
fc.connect(key_file="~/fincanva-api-key.txt")   # or a text file that holds the key alone

sim = fc.simulate("66f1c0a2b3d4e5f60718293b", start=2008)   # a saved strategy of yours, or a public one
print(sim.headline.strategy.cagr, sim.headline.strategy.sharpe)

ax = sim.equity().plot(title=sim.strategy_name)   # growth since the start: strategy beside benchmark
sim.regimes().shade(ax)                           # the risk-off periods in grey
plt.show()

sim.monthly_returns().loc["2020"]                 # one row per month
sim.metrics().to_frame()                          # every metric, strategy beside benchmark
sim.stress(volatility_multiplier=2.0).to_frame()  # the risk under a harsher view
sim.cone(horizon_days=1260)                       # a Monte Carlo cone, five years ahead
sim.trust().intervals()                           # bootstrap intervals of return, Sharpe, drawdown
sim.positions()                                   # what it holds today

assets = ["SPY", "TLT", "GLD"]
w = fc.allocation.weights(fc.allocation.RiskParity(), assets)    # today's weights by a method of the catalogue
w.weights, w.as_of                                                # by permaTicker, and the date they are for
fc.allocation.efficient_frontier(assets, allow_short=False).plot()
fc.allocation.walk_forward(fc.allocation.InverseVolatility(), assets, start=2015, rebalance_months=3).metrics.sharpe
fc.estimators.estimate(assets, fc.estimators.correlation.SpearmanOnReturns).matrix
r = fc.risk.regime(fc.risk.presets.Trend200)                     # risk-on or risk-off now, and since when
r.state, r.since, r.history

fc.raw                  # every API operation as a typed function, one to one
fc.allocation           # the allocation methods, one class each
fc.risk.presets         # the risk condition presets
fc.filters              # the screening filters, grouped as in the app
fc.estimators           # the covariance and correlation estimators

try:
    fc.allocation.walk_forward("risk_parity", assets, start=1990)
except fc.LicenceRefused as refused:   # raised only when a request reaches the protected long-run history
    refused.first_allowed_dates         # by permaTicker: the first date to ask again from (None: leave it out)

fc.connect() calls Fincanva at https://app.fincanva.com. To call another address, pass it as fc.connect(base_url="https://...") or set FINCANVA_BASE_URL: the origin alone, or the origin followed by /api/v1/research. The address must use https (plain http is accepted for localhost only), so the key never travels unencrypted.

Python 3.10 or later. Without pandas, the typed results (sim.headline, sim.metrics(), sim.trust(), sim.stress(), sim.regimes()) work as they are, and a method that returns a DataFrame raises fc.MissingDependency, naming the extra to install, before it spends anything. The research results (w.weights, r.history, ...) answer a dict or a list instead of a pandas object.

The designed surface

Built on fc.raw alone: every method calls one API operation through it, never a transport of its own. Every number is the API's own; a DataFrame reshapes an answer and never computes a figure.

Call Returns API operation
fc.simulate(strategy_id, *, start, benchmark, base_currency, starting_capital, variant) Simulation simulate_strategy
fc.Simulation(simulation_id, *, variant), fc.Simulation.from_answer(answer) Simulation none
fc.Variant(costs=False, reinvest=True, taxes=False); sim.with_variant(costs=True) the money-management variant none
sim.headline, sim.strategy_name, sim.start_year, sim.benchmark_name, ... typed, from the run none
sim.metrics() results.Metrics: typed; .to_frame(), .by_year() get_simulation_metrics
sim.equity(), sim.drawdown(), sim.equity_series(part, *, view, inflation_adjusted) DataFrame / Series by date get_simulation_equity
sim.monthly_returns(), sim.yearly_returns() DataFrame by month / year get_simulation_monthly_returns
sim.allocations(measure, *, sub_strategies) DataFrame by date, one column per sub-strategy get_simulation_allocations
sim.positions(on, *, capital), sim.target_positions(...), sim.orders(...) DataFrame get_simulation_positions
sim.regimes() results.Regimes: typed; .periods(), .to_frame(), .shade(ax) get_regime_timeline
sim.stress(*, annual_return_view, volatility_multiplier) results.StressTest: typed; .to_frame() run_stress_test
sim.cone(*, horizon_days, method, scenarios) DataFrame by day: p5 to p95 get_projection_cone
sim.trust(*, method, resamples) results.Trust: typed; .intervals(), .walk_forward() get_backtest_trust
sim.correlations(*, year), sim.rolling_correlation(a, b) DataFrame of pairs / Series by date get_simulation_correlations, get_rolling_correlation

Every read is made on the simulation's own variant, so one object's results agree, and is kept on the object: asking again spends nothing. Positions are always the base variant's, as the API reports them.

The allocation methods and the risk-on/off rules, called from the catalogue each choice is made from:

Call Returns API operation
fc.allocation.weights(method, assets, *, as_of, lookback_months, covariance_estimator, correlation_estimator) results.Weights: .weights by permaTicker, .as_of, .instruments, .to_frame() compute_weights
fc.allocation.combined_weights(method, strategy_id, *, as_of, lookback_months, covariance_estimator, timeout) results.CombinedWeights: .weights by sub-strategy id, .rotation_date, .profile compute_combined_weights
fc.allocation.efficient_frontier(assets, *, as_of, lookback_months, covariance_estimator, allow_short, min_weight, max_weight, limit_weights, points, place) results.Frontier: .points, .minimum_volatility, .maximum_sharpe, .maximum_return, .placed, .plot(ax) efficient_frontier
fc.allocation.walk_forward(method, assets, *, start, as_of, rebalance_months, lookback_months, covariance_estimator, correlation_estimator, variant, timeout) results.WalkForward: .metrics, .years, .walk_forward_years, .rotations walk_forward
fc.estimators.estimate(assets, estimator, *, matrix, as_of, lookback_months) results.Estimate: .matrix by permaTicker, .kind, .estimator estimate_covariance
fc.risk.regime(rule, *, start, as_of, strategy_id, timeout) results.RuleRegime: .state, .since, .history, .periods(), .shade(ax) compute_regime

method is an entry of fc.allocation with its settings (fc.allocation.MeanVariance(objective="minimum_volatility")), the entry alone, or its id; its settings are checked against the level the call uses (inside a strategy, or a Combined's) before anything is sent. An estimator of fc.estimators.covariance or fc.estimators.correlation carries its own settings (ExponentiallyWeighted(decay_factor=0.97)) and chooses the matrix. rule is a preset of fc.risk.presets, a preset's id, or a rule of a type as create_strategy takes a risk condition. Each result keeps the operation's typed result as .result, beside .summary and .assumed.

Your library and your real holdings (K), batches, pipelines and long runs (P), strategy discovery (S), explanations (X), your own series (U) and Fin Research (L), each its own module:

Call Returns API operation
fc.library.strategies(*, limit, offset), .live_strategies(...), .screeners(...) library.Listing: the typed entries; .total, .next_offset, .allowance, .to_frame() list_my_strategies, list_my_live_strategies, list_my_screeners
fc.library.strategy(strategy_id), fc.library.screener(screener_id) the saved item in full, .definition as create_strategy / create_screener take it get_my_strategy, get_my_screener
fc.review.positions_to_weights(positions, *, cash, as_of, base_currency) review.PositionWeights: .weights by permaTicker, .total_value, .stale, .to_frame() review_strategy
fc.review.rebalance_plan(current, target, *, current_cash, target_cash, capital, base_currency, minimum_trade_weight, slippage, transaction_cost) review.RebalancePlan: .trades, .dropped_trades, .turnover, .estimated_costs, .post_trade_weights review_strategy
fc.review.live_trades(*, on, since, strategy_ids) review.LiveTrades: .strategies, .refused, .to_frame() review_strategy
fc.review.health_check(simulation, *, as_of, window_months, factors, regime_series, episodes, wait, timeout) review.HealthCheck: .priorities, .not_computed, .episodes(), every section typed review_strategy
fc.Job(job_id): .status(), .wait(timeout), .cancel(), .answer(); fc.jobs.cancel(job_id) jobs.JobStatus; the run's designed result; jobs.Cancellation get_result, cancel_job
fc.batch(calls, *, wait, timeout) with fc.Call(operation, **arguments) batches.Batch: one BatchItem per call (.result, .answer(), .error, .job, .get()), .errors, .counts run_batch
fc.pipeline({step_id: fc.Call(...)}, *, wait, timeout) with fc.from_step(step_id, pointer) batches.Pipeline: each step by id, as BatchItem run_pipeline
fc.research_guide(*, query, family, tool, method) batches.Guide: .scenarios, .tool get_research_guide
fc.discovery.discover_strategy(strategy_id, space, *, validation, folds, fold_years, objective, constraints, max_trials, ...) with Choices, Range, Alternatives discovery.Discovery: .shortlist, .best, .pbo, .multiple_testing, .to_frame(), .trials() discover
fc.discovery.discover_risk_rule(...), .robust_parameter_region(...), .improve_strategy(...) discovery.Discovery: also .baseline, .region, .robust_centre, .proposals discover
fc.discovery.trials(discovery_id, *, limit, offset) discovery.DiscoveryTrials: .trials, .to_frame(), .next_page() discover
fc.explain.performance(simulation, *, year, by_sub_strategy, by_asset, by_regime, by_factor, factors, drag, variant) explain.PerformanceExplanation: .sub_strategies(), .assets(), .regimes(), .factors(), .drag explain
fc.explain.trade(simulation, asset, on, *, variant) explain.TradeExplanation: .position, .entry, .regime, .selection explain
fc.explain.what_if(strategy_id, changed_strategy_id, *, start, variant, wait, timeout) explain.WhatIf: .to_frame(), .years(), .relative_growth explain
fc.my_series.upload(name, points, *, kind), .list(), .delete(series) my_series.UserSeries: .reference (user:u_..., where a method names a series); SeriesList; the id deleted my_series
fc.fin_research.start(question, *, strategy_ids, screener_ids, language); ResearchSession(session_id): .get(), .wait(), .answer(), .approve(), .edit_plan(), .redirect(), .follow_up(), .cancel(), .report(), .refresh(), .schedule(), .delete(); fc.fin_research.sessions(), .schedules(), .delete_schedule() fin_research.ResearchSession, Report (.text() shows each cited figure as its display), Schedule research

Market research, one module per family: valuation, fundamentals, the universe of instruments, screener runs and options. Each function calls one API operation, a method or a mode of it, and each result keeps the operation's typed result as .result (every field the API answered) with named views, as the research results above do; a family's result classes are named on its module (fc.valuation.ReverseDcf). An argument left out is not sent: the API applies its default.

Call Returns API operation
fc.valuation.reverse_dcf(asset, *, as_of, valuation_method, horizon_years, record_years, history_window_years, change_months, peer_group, discount_basis, discount_rate, terminal_growth) ReverseDcf: .implied_growth, .implied_return, .excess_return_over_capm, .peer_percentile, .peer_gap (each a Figure(value, reason)), .figures, .to_frame() value_company, reverse_dcf
fc.valuation.dcf_valuation(asset, *, stage1_growth, ...) DcfValuation: .scenarios (bear, base, bull, yours), .scenario(name), .to_frame() value_company, dcf_valuation
fc.valuation.dcf_sensitivity(asset, *, discount_rates, terminal_growths, stage1_growth, ...) DcfSensitivity: .grid (rates by growths), .value_at(rate, growth) value_company, dcf_sensitivity
fc.valuation.implied_growth_history(asset, *, history_years, ...) ImpliedGrowthHistory: .implied, .realized by month-end, .to_frame() value_company, implied_growth_history
fc.fundamentals.report(asset, *, as_of) Fundamentals: .filed, .income, .balance_sheet, .cash_flow, .ratios, ..., .to_frame() analyze_fundamentals, get_fundamentals
fc.fundamentals.trends(asset, *, start, as_of) FinancialTrends: .years, .growth, .streaks analyze_fundamentals, financial_trends
fc.fundamentals.metric_history(asset, field, *, filter, start, as_of) MetricHistory: .series, .latest (percentile, z-score) analyze_fundamentals, get_metric_history
fc.fundamentals.valuation_vs_peers(asset, filter, *, start, as_of) PeerValuation: .to_frame() (the stock, its sector, its market, its index), .latest analyze_fundamentals, valuation_vs_peers
fc.fundamentals.market_valuation(*, start, as_of) MarketValuation: .to_frame() (Shiller P/E, Buffett indicator, its deviation), .latest analyze_fundamentals, market_valuation
fc.universe.find(queries, *, asset_class, region, currency, ucits, accumulating, candidates) Found: .resolved, .unresolved (never guessed), .handle, .to_frame() find_assets
fc.universe.coverage(assets, *, datasets, fields) Coverage: .span(asset, dataset), .unknown, .to_frame() get_data_coverage
fc.universe.describe(asset) AssetDescription: .name, .type, .sector, .size_tier, .statistics, .availability explore_universe, describe_asset
fc.universe.universes(*, as_of) Universes: .universes, .indices, .sectors explore_universe, list_universes
fc.universe.index_members(index) IndexMembers: .date, .perma_tickers, .to_frame() (today's membership only) explore_universe, get_index_members
fc.universe.search_by_exposure(exposure, *, region, accumulating, as_of) Exposures: .default_funds, .to_frame() explore_universe, search_by_exposure
fc.universe.datasets() Datasets: .version, .fields(dataset), .to_frame() explore_universe, list_datasets
fc.screens.screen(screener, *, limit, timeout) Screen: .picks, .rows, .emptied_by, .handle, .to_frame() run_screen, screen_assets
fc.screens.backtest(screener, *, timeout, wait) ScreenBacktest: .horizons, .path, .row_impacts() run_screen, backtest_screen
fc.screens.improve(screener, *, timeout, wait), fc.screens.suggest(universe, *, name, timeout, wait) ScreenSuggestion: .robust, .outperformance_score, .trials_evaluated, .screener_id, .problems run_screen, improve_screen / suggest_screen
fc.screens.membership_changes(screener, since, *, as_of, timeout) MembershipChanges: .entered, .left, exact counts run_screen, screen_membership_changes
fc.screens.collect(run_id, *, timeout); wait=False answers a fc.Job the run's result get_result
fc.options.price(right, *, underlying_price, strike, days_to_expiry, volatility, model, rate, dividend_yield, dividends) (model and rate required by every calculator) OptionPrice: .price, .greeks, .units price_options, price_option
fc.options.implied_volatility(right, *, ..., option_price, model, rate) ImpliedVolatility: .implied_volatility, .reason, .greeks price_options, implied_volatility
fc.options.payoff(legs, *, underlying_price, model, rate, ...) with fc.options.Leg(...) StrategyPayoff: .profit, .breakevens, .max_profit, .max_loss, .probability_of_profit, .plot(ax) price_options, strategy_payoff
fc.options.expiries(underlying, *, as_of), fc.options.chain(underlying, expiry, *, greeks, min_abs_delta, root, as_of) Expiries; OptionChain: .to_frame(), .calls(), .puts() analyze_options, get_option_expiries / get_option_chain
fc.options.term_structure(underlying, ...), fc.options.skew(underlying, ...) TermStructure, Skew: .horizons, .expiries, .history analyze_options, volatility_term_structure / volatility_skew
fc.options.implied_vs_realized(underlying, ...) ImpliedVsRealized: .iv30, .iv_rank30, .iv_rv_spread, .realised, .vrp, .history analyze_options, implied_vs_realized
fc.options.expected_move(underlying, to, *, measure, as_of) ExpectedMove: .expected_move_pct, .target_date, .reason analyze_options, expected_move
fc.options.positioning(underlying, *, profile, expiry, band_width, history_from) Positioning: .pc_volume, .max_pain_strike, .gex_total, .walls, .bands, .history analyze_options, options_positioning
fc.options.earnings_history(underlying, *, last_events, pair_type) EarningsHistory: .events, .aggregates analyze_options, earnings_options_history

backtest, improve and suggest are long runs, waited for like a simulation (a screener run is never cancelled); improve and suggest save what they find as a new screener and are refused to an app set to read-only (ToolsetDisabled). A figure that does not apply is None with its reason, never 0: a valuation that does not apply (.reason), reverse_dcf's peer figures while the peers are not read (peer_group_too_small), an implied volatility no price gives (no_volatility_reprices_it).

The analysis families, one module each over one API operation that takes the method as method (each function sends one method; the API operation and method are named in its documentation):

Call Returns API operation, method
fc.instruments.analyze(assets, *, start, benchmark, variant, as_of, years, sortino, factor_betas) Backtests: .metrics, .years(), .factor_betas() analyze_instruments, analyze_assets
fc.instruments.compare(assets, rank_on, *, start, order, ...) Ranking: .rows, .best compare_assets
fc.instruments.performance_history(assets, *, start, growth, real, drawdown, ...) PerformanceHistory: .growth(), .drawdown() by date get_performance_history
fc.instruments.rolling(assets, statistic, *, start, factor, rolling_months, window_years, ...) RollingStatistics: .lines(), .window_outcomes(), .aggregates() rolling_statistics
fc.instruments.calendar_returns(assets, *, start, ...) CalendarReturns: .monthly() by month, .years() calendar_returns
fc.instruments.drawdowns(assets, *, start, min_depth, top, ...) Drawdowns: .episodes(), .lines(), .max_drawdown drawdown_analysis
fc.instruments.return_distribution(assets, *, start, monthly, bins, ...) ReturnDistribution: .summary(), .histogram() return_distribution
fc.instruments.seasonality(assets, *, start, day_of_week, turn_of_month, ...) Seasonality: .month_of_year(), .day_of_week(), .turn_of_month() seasonality
fc.instruments.event_study(assets, *, benchmark, start, events, events_series, earnings, ...) EventStudy: .car(), .path(), .events(), .skipped() event_study
fc.relationships.betas(assets, against, *, lookback_months, as_of) Betas: .betas, .to_frame() analyze_relationships, beta_analysis
fc.relationships.expected_returns(assets, *, lookback_months, black_litterman, momentum_months, view_confidence, covariance_estimator) ExpectedReturns: .annualized estimate_expected_returns
fc.relationships.factor_exposure(assets, *, start, year, benchmark, variant) FactorExposure: .factors() factor_exposure
fc.relationships.factor_regression(assets, *, simulation, start, factors, monthly, rolling_months, ...) FactorRegression: .betas(), .fit(), .rolling() factor_regression
fc.relationships.pairs(first, second, *, lookback_months, johansen, z_score_window_days) Pair: .cointegrated, .hedge_ratio, .half_life_days, .z_score pairs_analysis
fc.relationships.risk_contributions(weights, *, lookback_months, covariance_estimator) RiskContributions: .volatility, .risk_shares risk_contributions
fc.relationships.correlation_matrix(assets, *, lookback_months, estimator, clustered) CorrelationMatrix: .matrix in its clustered order correlation_matrix
fc.relationships.regime_behaviour(rule, assets, *, simulation, start, ...) RegimeBehaviour: .states(), .state, .time_in_regime asset_regime_behaviour
fc.macro.series(kind, *, asset, start, as_of) MacroSeries: .points by date, .latest analyze_macro, get_macro_series
fc.macro.snapshot(*, as_of, start) MacroSnapshot: .latest() by kind macro_snapshot
fc.macro.sensitivity(assets, *, start, series, columns, monthly, benchmark, variant) MacroSensitivity: .betas(), .fit() or .columns() macro_sensitivity
fc.scenarios.crisis_replay(assets, *, start, episodes, ...) CrisisReplay: .replay(), .episodes run_scenario, crisis_replay
fc.scenarios.regime_projection(assets, *, start, horizon_days, scenarios, method, state_count, regime_series, ...) RegimeProjection: .cone(), .regime regime_conditional_projection
fc.scenarios.macro_scenario(assets, shocks, *, start, horizon_months, monthly, ...) MacroScenario: .impacts(), .betas() macro_scenario
fc.scenarios.historical_analogues(assets, *, start, features, horizon_months, count, minimum_gap_months, ...) HistoricalAnalogues: .analogues(), .following_returns(), .today historical_analogues
fc.robustness.cone(returns, *, horizon_days, scenarios, method) SeriesCone: .bands by day analyse_return_series, projection_cone_on_series
fc.robustness.trust(returns, *, risk_free_rate, resamples, method) SeriesTrust: .intervals() backtest_trust_on_series
fc.robustness.deflated_sharpe(sharpe, trial_sharpes, *, observations, skewness, kurtosis) DeflatedSharpe: .probability deflated_sharpe
fc.robustness.sweep(strategy_id, axis, *, rank_by, start, variant) Sweep: .cells(), .control, .best stress_strategy, sweep
fc.robustness.check_overfitting(strategy_id, axis, *, start, variant) OverfittingCheck: .trials(), .best check_overfitting
fc.robustness.stability_report(strategy_id, axis, *, rank_by, slicing, slice_years, step_years, minimum_era_days, ...) StabilityReport: .stability(), .ranks() get_stability_report

Every figure is an instrument's one-instrument backtest, a window of prices, a macro series or the numbers you give, as the engine answers it. A method that computes backtests (analyze, drawdowns, return_distribution, seasonality, event_study, factor_exposure, factor_regression, regime_behaviour, the regression form of macro.sensitivity, every scenario, every sweep) is a long run: it waits up to timeout seconds, then raises RunStillRunning, whose run_id the family's collect(run_id) or fc.Job(run_id) turns into the same typed result later. compare, performance_history, rolling and calendar_returns read backtests analyze computed, with the same instruments, start, benchmark and variant, and are refused NotFoundError before. variant is a fc.Variant. Each result keeps the method's typed result as .result; its views answer pandas objects when pandas is installed and plain Python otherwise, and to_frame() always needs pandas.

Every long run is one fc.Job. A call that may be a long run (a simulation, health_check, a search, a what-if, a batch or a pipeline the request cannot finish, a screener's backtest or search, a method computed from backtests) waits for it by default, up to timeout seconds; where it takes wait=False, it returns a fc.Job at once instead (job.wait(), job.cancel()), already done when the API answered at once. A wait that runs out raises RunStillRunning: the run goes on, and fc.Job(error.run_id).wait() picks it up and finishes as the same designed result, whichever family started it. Following and cancelling a run are free; job.cancel() stops a batch, a discovery, a walk-forward, a sweep or a method computed from backtests, and refuses the rest. A batch item that is itself a long run holds its own Job. A Fin Research session is not a run: when session.wait() runs out, the RunStillRunning it raises has no run_id, and fc.fin_research.ResearchSession(session_id) reads the session again.

The errors the API answers each have a class under fc.FincanvaError: AuthenticationError, ValidationError, PlanLimitError (the plan, an allowance or the per-minute cap), ToolsetDisabled (the user's settings for a connected app: .family, .read_only), LicenceRefused (data that may not leave Fincanva: for the protected long-run history, .first_allowed_dates by permaTicker; otherwise .dataset, .licence_class, .surface), NotFoundError, SavedStrategyChanged, RunFailed, RunStillRunning, ServiceUnavailable.

Design notes

  • Install extras. fincanva[pandas] (the DataFrames), fincanva[plot] (matplotlib, for Regimes.shade() without an axes), fincanva[all]. The core needs httpx and pydantic only. import fincanva never imports pandas, matplotlib or the generated models, and neither does importing a catalogue.
  • Typed results are the generated models. fincanva.results subclasses the generated result model of each simulation answer and adds views, so the fields, names and documentation are fc.raw's, and a field the API adds appears in both at once. A research result keeps that model as .result instead, because its named views (.weights, .matrix, .history) answer a pandas object or plain Python where the model has a list.
  • No instrument as a benchmark yet. benchmark= takes "strategy", "none" or a strategy id, as the API does; fc.simulate(..., benchmark="ACWI") is refused before anything is sent.
  • No "excluded" list. compute_weights answers no entry for an instrument with no price on the date and states no list of what it left out; Weights shows what the API answered and never infers the rest.
  • Every other operation: through fc.raw. The designed surface above covers every family of the API but three groups, which are in fc.raw only, one typed function each, with the operation's own arguments and typed result: building and saving strategies (create_strategy, edit_strategy, replace_strategy, validate_strategy, explain_strategy, describe_strategy_model; a designed fc.Strategy is not in this version), building and saving screeners (create_screener, edit_screener, replace_screener, validate_screener, explain_screener, describe_screen_filter), and more reads on simulations (compare_simulations, get_contribution_analysis, get_simulation_trade_history, get_start_date_sensitivity, get_strategies_analytics, get_strategies_returns, get_rotation_dates, get_todays_rotations). The four listings (list_allocation_methods, list_covariance_estimators, list_risk_rule_presets, list_screen_filters) are what the catalogues fc.allocation, fc.estimators, fc.risk.presets and fc.filters were recorded from; fc.raw asks them live.

Metadata

Release files for fincanva 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fincanva 1.0.0
File Size Uploaded Provenance
fincanva-1.0.0.tar.gz 437.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fincanva 1.0.0
File Interpreter ABI Platform
fincanva-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / fincanva-1.0.0.tar.gz

Download URL fincanva-1.0.0.tar.gz
Size 437.2 kB
Tags Source
SHA-256 checksum
How to use checksums
5240e4482884e2eaacf62595c2e648707174f93fac5f1a799df281dd010db479
BLAKE2b-256 checksum
How to use checksums
0a406fd8d4c04a8069f12b3728fec0d10ca1316d8512059e2cf7174296bf79d9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Release files / fincanva-1.0.0-py3-none-any.whl

Download URL fincanva-1.0.0-py3-none-any.whl
Size 572.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a38006b8b6b21a7038fdafd866f0cde51573cc2edf6bf9e427342bbfe4595f56
BLAKE2b-256 checksum
How to use checksums
3218c99f094950ee3d65ba54337f3c9ba19691f24d77972463e603a094399727
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Security for fincanva 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for fincanva-1.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page