Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for fee/commission as % when backtesting #227

Open
ibyter opened this issue Oct 2, 2024 · 3 comments
Open

Support for fee/commission as % when backtesting #227

ibyter opened this issue Oct 2, 2024 · 3 comments

Comments

@ibyter
Copy link

ibyter commented Oct 2, 2024

Describe the solution you'd like
Add a commission/fee as % when performing backtesting.

Almost all brokers charge a percentage fee on each executed trade which should be taken into account when calculating outcome

@cinar
Copy link
Owner

cinar commented Oct 7, 2024

Thank you for the future request. Let me see if I can add this quickly.

@kfimchenko
Copy link

Thank you for the future request. Let me see if I can add this quickly.

Hi! Any ideas? Or maybe there is another way to simulate a broker's commission? I have just backtested the same basic strategies and received like over 9000 percent profit, which makes no sense without a commission.

@ibyter
Copy link
Author

ibyter commented Jan 24, 2025

@kfimchenko for your reference, the way I worked around it to add the fee rate, is by modifying the module cache one my local filesystem e.g. here in Mac ~/go/pkg/mod/github.com/cinar/indicator/[email protected]/strategy/outcome.go, and the calculation is done as follows:

package strategy

import "github.com/cinar/indicator/v2/helper"

func Outcome[T helper.Number](values <-chan T, actions <-chan Action) <-chan float64 {
        totalBudget := 1000000.0 // Total funds available for trading
        balance := totalBudget
        shares := 0.0
        totalInvested := 0.0 // Total amount invested in buy actions
        feeRate := 0.002
        sharesPerBuy := 1.0 // Fixed number of shares to buy per Buy action

        return helper.Operate(values, actions, func(value T, action Action) float64 {
                switch action {
                case Buy:
                        // Calculate the total cost for the shares
                        totalCost := sharesPerBuy * float64(value)
                        // Calculate the fee based on the total cost
                        fee := totalCost * feeRate
                        // Total cost including the fee
                        totalCostIncludingFee := totalCost + fee

                        // Check if there's enough balance to cover the total cost including the fee
                        if balance >= totalCostIncludingFee {
                                shares += sharesPerBuy
                                balance -= totalCostIncludingFee
                                totalInvested += totalCostIncludingFee
                        }
                        // If not enough balance, ignore the Buy action

                case Sell:
                        if shares > 0 {
                                // Calculate the proceeds from selling the shares
                                proceeds := shares * float64(value)
                                // Calculate the fee based on the proceeds
                                fee := proceeds * feeRate
                                // Net proceeds after deducting the fee
                                netProceeds := proceeds - fee
                                balance += netProceeds
                                shares = 0
                        }
                        // No action needed for Hold or other actions
                }

                // Corrected Net Gain Calculation
                netGain := (balance + (shares * float64(value))) - totalBudget
                if totalInvested > 0 {
                        roiFraction := netGain / totalInvested
                        return roiFraction
                } else {
                        return 0.0 // Or handle as appropriate when no investment has been made
                }
        })
}

Moreover, this version also handles consecutive buy actions, which is not present in the original library.

I know it's hacky, but it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants