I am implementing a trading system, and I want to use the same code for both live trading and backtesting. When doing live trading, I need to persist everything that happens, but when backtesting, I would like to use the same classes and logic but not persist them (for speed and because I have no reason to store them).
I thought I could do this simply by not calling save() on them, but I've run into a problem. I have an Account class that includes a hasMany collection of Position objects. The trouble is that I need to find the right Position in the Account, but it seems that I can't, since it's never been saved. I tried iterating through the hasMany collection of Positions but there's nothing in there, even though I constructed a Position object and added it to the account with addToPositions(). I guess this won't be meaningful until after that call to save() that I'm trying to avoid.
Is there a way to reuse the same classes for both persistant and transient purposes, or am I trying to commit an unnatural act? I am open to any suggestions for how to reuse these classes in both scenarios.
Update (adding code samples):
Account.groovy:
class Account {
String name
static belongsTo = [user:S2User]
static hasMany = [positions:Position, transactions:Transaction]
}
SimAccount.groovy:
class SimAccount extends Account {
}
Position.groovy:
class Position implements Serializable {
String symbol
static belongsTo = [account:Account]
}
BacktestController.groovy:
// add Account
def acct = new SimAccount(name:"backtest")
// add position
def pos = new Position(symbol:'SIRI')
acct.addToPositions(pos)
Strategy.groovy:
println "apply($accounts, $quotes) [$name]"
accounts.each{ a ->
println " acct $a (${a?.name})"
a?.positions?.each{ p ->
println " pos: $p"
}
}
def siri = Position.findByAccountAndSymbol(accounts[0], 'SIRI')
println "siri pos: $siri"
The output from Strategy.groovy when the objects have been saved is
apply([com.lossless.account.SimAccount : 1, null], [:]) [Live SIRI 50k]
acct com.lossless.account.SimAccount : 1 (sim1)
pos: com.lossless.account.Position : 1
acct null (null)
siri pos: com.lossless.account.Position : 1
The output when the objects have not been saved is
apply([com.lossless.account.SimAccount : null, null], [bid:1.74, ask:1.74]) [Backtest SIRI 50k]
acct com.lossless.account.SimAccount : null (backtest)
pos: com.lossless.account.Position : null
acct null (null)
| Error 2013-01-21 03:11:11,984 [http-bio-8080-exec-2] ERROR errors.GrailsExceptionResolver - TransientObjectException occurred when processing request: [POST] /lossless/backtest/index - parameters:
object references an unsaved transient instance - save the transient instance before flushing: com.lossless.account.Account. Stacktrace follows:
Message: object references an unsaved transient instance - save the transient instance before flushing: com.lossless.account.Account
Line | Method
->> 105 | doCall in org.grails.datastore.gorm.GormStaticApi$_methodMissing_closure2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 66 | apply in com.lossless.Strategy
Line 66 in Strategy.groovy is the call to Position.findByAccountAndSymbol()
.