Assessing Performance from a CSV of Precomputed Trades
Summary
The document addresses how to evaluate a set of trades generated outside a backtesting package. Its key distinction is that the trade signals have already been produced; the remaining task is to calculate portfolio performance, equity, and profit and loss from those transactions. One suggested workflow imports the CSV, initializes an account and portfolio, adds each transaction, updates valuations, and charts positions. It also mentions adapting a Python backtesting library to act on dated buy and sell records, or loading market data through a custom feed.
The discussion reflects the questioner's long holding periods and willingness to use daily closing prices or VWAP while simplifying commissions. It does not establish that these assumptions produce reliable performance estimates. Trade prices, fees, cash handling, and the relationship between external signals and the tested price series still need careful treatment. The answers offer implementation directions rather than a fully validated, ready-made CSV evaluation tool; one respondent concludes that custom coding may be necessary.
Key ideas
- A list of precomputed trades can be evaluated as portfolio transactions without recreating the signal logic.
- A portfolio ledger can track positions, account equity, and performance as transactions are added.
- Daily closing prices or VWAP may be practical valuation inputs for long-horizon trades, but they simplify execution assumptions.
- Backtesting libraries may require custom code or data feeds to consume external trade records.
- The discussion provides implementation approaches but no comparative performance evidence or turnkey solution.
Tags
Full text
# Software for backtesting outside strategies (CSV transaction upload)
# Software for backtesting outside strategies (CSV transaction upload)
I've developed some software which generates sets of trades, and I'd like to backtest those trades. My software currently outputs a CSV file with details of each trade:
```
2011-03-31,MSFT,Buy,100
2011-04-02,AAPL,Buy,50
2011-05-10,MSFT,Sell,100
```
Is there any backtesting software out there that lets you bring in a set of your own trades, and see how it would have done? All the software I've found so far requires to you write your algos directly in the package, and doesn't simply let you say 'Buy X, Sell Y'.
Edit based on comments:
- I don't include prices or commissions in my CSV because my play here is a long term play (timescale is months or even years). Having the backtesting software use the VWAP (or even just the day's close) is fine, and with most retail commissions fairly low I could either let the backtesting software add one in or just ignore it. I may not get perfect resolution but (I think) I'd be close enough.
- I can't use any of the packages that I've found because my algo doesn't work on the traditional technicals. Instead I'm looking (mostly) at independent stuff, such as 13f data feeds.
- I can definitely write something in R, or even in my own codebase, but I'm trying to save myself some work on my proof of concept.
## Answer by Joshua Ulrich (score 16, accepted)
https://quant.stackexchange.com/a/7694
You're not really asking how to backtest a strategy. You already have run a backtest to generate simulated trades. What you're asking for is a way to assess the performance of those simulated trades.
You can do this with the R package blotter. You'll need to setup your account and portfolio, then loop over each row in your CSV and call `addTxn`. For example:
```
trades <- read.csv("trades.csv")
symbols <- unique(trades$symbol)
# Set up a portfolio object and an account object in blotter
initPortf(name='default', symbols=symbols, initDate=initDate)
initAcct(name='default', portfolios='default', initDate=initDate, initEq=initEq)
verbose = TRUE
for(i in 1:NROW(trades)) {
addTxn('default', Symbol=trades$symbol[i], TxnDate=trades$date[i],
TxnPrice={"object-with-price"}, TxnQty=trades$quantity[i], TxnFees=0, verbose=verbose)
}
# Calculate P&L and resulting equity with blotter
updatePortf(Portfolio='default', Dates=CurrentDate)
updateAcct(name='default', Dates=CurrentDate)
updateEndEq(Account='default', Dates=CurrentDate)
# Look at performance
chart.Posn(Portfolio='defaut',Symbol='MSFT')
chart.Posn(Portfolio='defaut',Symbol='AAPL')
```
## Answer by dordal (score 3)
https://quant.stackexchange.com/a/7691
Answering my own question... based on the above comments and a lot of research, it looks like there aren't any packages out there that do this 'out of the box'. So coding your own is the best way to go.
## Answer by K3---rnc (score 1)
https://quant.stackexchange.com/a/43570
With a backtesting library such as Backtesting.py and some Python, you could do something like:
```
import pandas as pd
trades = pd.read_csv('my_trades.csv',
index_col=0,
parse_dates=True,
infer_datetime_format=True)
buys = trades[trades.iloc[:,1] == 'Buy']
sells = trades[trades.iloc[:,1] == 'Sell']
from backtesting import Strategy
class MyTrades(Strategy):
def next(self):
if self.data.index in buys:
self.buy()
if self.data.index in sells:
self.sell()
```
## Answer by kenorb (score 0)
https://quant.stackexchange.com/a/58848
With Backtrader in Python should be easy.
For example:
```
from datetime import datetime
import backtrader as bt
class SmaCross(bt.SignalStrategy):
def __init__(self):
sma1, sma2 = bt.ind.SMA(period=10), bt.ind.SMA(period=30)
crossover = bt.ind.CrossOver(sma1, sma2)
self.signal_add(bt.SIGNAL_LONG, crossover)
cerebro = bt.Cerebro()
cerebro.addstrategy(SmaCross)
data0 = bt.feeds.YahooFinanceData(dataname='MSFT', fromdate=datetime(2011, 1, 1),
todate=datetime(2012, 12, 31))
cerebro.adddata(data0)
cerebro.run()
cerebro.plot()
```
To use your own CSV data, you can define your own custom feed class, e.g.:
```
import itertools
...
import backtrader as bt
class MyCSVData(bt.CSVDataBase):
def start(self):
# Nothing to do for this data feed type
pass
def stop(self):
# Nothing to do for this data feed type
pass
def _loadline(self, linetokens):
i = itertools.count(0)
dttxt = linetokens[next(i)]
# Format is YYYY-MM-DD
y = int(dttxt[0:4])
m = int(dttxt[5:7])
d = int(dttxt[8:10])
dt = datetime.datetime(y, m, d)
dtnum = date2num(dt)
self.lines.datetime[0] = dtnum
self.lines.open[0] = float(linetokens[next(i)])
self.lines.high[0] = float(linetokens[next(i)])
self.lines.low[0] = float(linetokens[next(i)])
self.lines.close[0] = float(linetokens[next(i)])
self.lines.volume[0] = float(linetokens[next(i)])
self.lines.openinterest[0] = float(linetokens[next(i)])
return True
```
Then load your data and add your strategy:
```
cerebro = bt.Cerebro()
data = MyCSVData(dataname='file.csv', fromdate=datetime(2019, 1, 1), todate=datetime(2019, 2, 28))
cerebro.adddata(data)
cerebro.addstrategy(MyStrategy)
```
Docs: https://www.backtrader.com/
## Answer by user42108 (score 0)
https://quant.stackexchange.com/a/58849
TuringTrader (https://www.turingtrader.org/) might be worth a look. Or Zorro (https://www.zorro-trader.com/).Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.