{"id":34156946,"url":"https://github.com/grinply/kate-backtester","last_synced_at":"2026-03-09T16:36:42.421Z","repository":{"id":57576929,"uuid":"355325570","full_name":"grinply/kate-backtester","owner":"grinply","description":"A fast and simple backtest implementation for algorithmic trading in golang","archived":false,"fork":false,"pushed_at":"2021-08-19T21:35:16.000Z","size":3273,"stargazers_count":16,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-06-20T12:46:54.729Z","etag":null,"topics":["algorithmic-trading","backtesting-engine","backtesting-frameworks","backtesting-trading-strategies","backtests","crypto-trading","cryptocurrency","finance","financial-analysis","forex","forex-trading","go","golang","investing","trading-simulation","trading-strategies"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grinply.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-06T20:47:38.000Z","updated_at":"2024-05-08T00:27:06.000Z","dependencies_parsed_at":"2022-09-11T23:02:42.710Z","dependency_job_id":null,"html_url":"https://github.com/grinply/kate-backtester","commit_stats":null,"previous_names":["victorl2/kate-backtest","victorl2/kate-backtester"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/grinply/kate-backtester","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grinply%2Fkate-backtester","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grinply%2Fkate-backtester/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grinply%2Fkate-backtester/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grinply%2Fkate-backtester/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grinply","download_url":"https://codeload.github.com/grinply/kate-backtester/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grinply%2Fkate-backtester/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30302651,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T14:33:48.460Z","status":"ssl_error","status_checked_at":"2026-03-09T14:33:48.027Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithmic-trading","backtesting-engine","backtesting-frameworks","backtesting-trading-strategies","backtests","crypto-trading","cryptocurrency","finance","financial-analysis","forex","forex-trading","go","golang","investing","trading-simulation","trading-strategies"],"created_at":"2025-12-15T07:37:45.429Z","updated_at":"2026-03-09T16:36:42.412Z","avatar_url":"https://github.com/grinply.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n[![Go Report Card](https://goreportcard.com/badge/github.com/victorl2/quick-backtest?style=flat-square)](https://goreportcard.com/report/github.com/victorl2/kate-backtester)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=victorl2_quick-backtest\u0026metric=sqale_rating)](https://sonarcloud.io/dashboard?id=victorl2_quick-backtest)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](/LICENSE.md)\n[![Go Reference](https://pkg.go.dev/badge/github.com/victorl2/kate-backtester.svg)](https://pkg.go.dev/github.com/victorl2/kate-backtester)\n# Kate Backtester\nA fast and simple backtest implementation for **algorithmic trading** focused on [cryptocurrencies](https://en.wikipedia.org/wiki/Cryptocurrency#:~:text=A%20cryptocurrency%2C%20crypto%20currency%20or,creation%20of%20additional%20coins%2C%20and) written in [GoLang](https://golang.org/).\n\n## Data\nThe price data used to run the backtests can be from any time interval, but it must contain a [**OHLCV**](https://en.wikipedia.org/wiki/Open-high-low-close_chart) structure _(**O**pen **H**igh **L**ow **C**lose **V**olume)_. It is possible to load data from **csv** files with the following format:\n\n| open      | high      | low       | close     | volume     \n|:---------:|:---------:|:---------:|:---------:|:----------\n| 7922.0700 | 7924.9900 | 7920.1600 | 7924.7500 | 9.90606700 \n| 7923.4300 | 7929.1400 | 7920.8000 | 7922.9000 | 15.83760800\n| 7923.1300 | 7934.0900 | 7922.9000 | 7932.2600 | 9.98577900\n\n## Usage\nTo start using **kate backtester** you will need to implement the [**Strategy interface**](https://github.com/victorl2/kate-backtester/blob/main/pkg/strategy.go) and provide a **csv** a dataset for execution. The Strategy interface contains 4 functions that describe how/when to trade: **PreProcessIndicators**, **OpenNewPosition**, **SetStoploss** and **SetTakeProfit**.\n\n### PreProcessIndicators\nAllows the strategy to pre calculate the indicators and values for reuse in the other functions, making the execution faster and less redundant. This pre processing step is the **first** function called with every new price data avaliable.\n### OpenNewPosition\nThis function is responsible for opening new trade positions when there are none open already, the function is called with every new price data to check, a nil return denotes that no positions should be open yet. When opening a position a OpenPositionEvt is returned containing the **Direction** for the trade _(LONG/SHORT)_ and the desired [leverage](https://blog.earn2trade.com/leverage-trading/), a possible return would be `return \u0026kate.OpenPositionEvt{Direction: kate.LONG, Leverage: 30}`\n\n### SetStoploss\nAs the name already implies this function is responsible for setting the stoploss price for the **already open position**, the function is called when new price data is avaliable and a position is open. This function makes possible changing the **stoploss** dynamically as the position evolves, the updated PNL is avaliable for checking. A nil return denotes that no changes should be made, a example return would be `return \u0026kate.StoplossEvt{Price: openPosition.EntryPrice * 0.995}` \n\n### SetTakeProfit\nThis function has the same behavior as **SetStoploss** but instead it manipulates the take profit price. A example return would be `return \u0026kate.TakeProfitEvt{Price: openPosition.EntryPrice * 1.005}`\n\nA [basic implementation](https://github.com/victorl2/kate-backtester/blob/main/examples/basic/main.go) where a strategy opens a long position every time the latest [close price](https://www.dailyfx.com/education/candlestick-patterns/how-to-read-candlestick-charts.html#:~:text=Close%20Price%3A,depends%20on%20the%20chart%20settings) is higher than the last close is: \n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/victorl2/kate-backtester/kate\"\n)\n\ntype SimpleStrategy struct{\n\tlastPrice    *kate.DataPoint\n\tcurrentPrice *kate.DataPoint\n}\n\nfunc main() {\n\tdata, err := kate.PricesFromCSV(\"../../testdata/ETHUSD5.csv\")\n\t\n\tif err != nil {\n\t\tpanic(\"could`t load data.\" + err.Error())\n\t}\n    kate.NewBacktester(\u0026SimpleStrategy{}, data)\n\tbacktester := kate.NewBacktester(\u0026SimpleStrategy{}, data)\n\tfmt.Println(backtester.Run())\n}\n\n//PreProcessIndicators allows the pre processing of indicators\nfunc (stg *SimpleStrategy) PreProcessIndicators(latestPrice kate.DataPoint) {\n\tstg.lastPrice = strategy.currentPrice\n\tstg.currentPrice = \u0026latestPrice\n}\n\n//OpenNewPosition process the next data point and checks if a position should be opened\nfunc (stg *SimpleStrategy) OpenNewPosition(latestPrice kate.DataPoint) *kate.OpenPositionEvt {\n\tif stg.lastPrice != nil \u0026\u0026 stg.currentPrice.Close() \u003e stg.lastPrice.Close() {\n\t\treturn \u0026kate.OpenPositionEvt{Direction: kate.LONG, Leverage: 30}\n\t}\n\treturn nil\n}\n\n//SetStoploss defines a stoploss for the current open position\nfunc (stg *SimpleStrategy) SetStoploss(openPosition kate.Position) *kate.StoplossEvt {\n\tif openPosition.Direction == kate.LONG \u0026\u0026 openPosition.Stoploss \u003c= 0 {\n\t\treturn \u0026kate.StoplossEvt{Price: openPosition.EntryPrice * 0.995}\n\t}\n\treturn nil\n}\n\n//SetTakeProfit defines a takeprofit for the current open position\nfunc (stg *SimpleStrategy) SetTakeProfit(openPosition kate.Position) *kate.TakeProfitEvt {\n\tif openPosition.Direction == kate.LONG \u0026\u0026 openPosition.TakeProfit \u003c= 0 {\n\t\treturn \u0026kate.TakeProfitEvt{Price: openPosition.EntryPrice * 1.005}\n\t}\n\treturn nil\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrinply%2Fkate-backtester","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrinply%2Fkate-backtester","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrinply%2Fkate-backtester/lists"}