问题
I have been scratching my head for the last few days trying to understand how to limit the number of position in a strategy. Its a channel breakout strategy (go long/shirt the 20d breakout channel with a 10d high/low stop loss.
I don't want the system to pyramid. Only 1 position is accepted i.e - if on day 1 I have a signal, and the market keeps trending, it will print new signals but they have to be dismissed as we are already in a position.
I tried everything i've found but i have been unable to achieve anything. I know I have to tweak with osMaxPos and addPosLimit but it seems i'm doing it wrong.
Here is my code. Thanks in advance.
#Import des données
GBPUSD <- getdata("GBPUSD.csv")
GBPUSD <- getdata("GBPUSD.csv")
AUDUSD <- getdata("AUDUSD.csv")
EURUSD <- getdata("EURUSD.csv")
XAUUSD <- getdata("XAUUSD.csv")
EURCHF <- getdata("EURCHF.csv")
### Création des devises
currency(c("USD","EUR","AUD","GBP","XAU","CHF"))
exchange_rate(c("EURUSD","GBPUSD","AUDUSD","XAUUSD","EURCHF"),"USD")
symbols <- c("GBPUSD","AUDUSD","EURUSD")
tradesize <- 1000000
init.date <- "2001-09-04" #date d'initialisation de l'environement
start.date <- "2001-10-01" #1ere date du jeu de donnée
end.date <- Sys.Date() #dernière date du jeu de donnée
initial.capital <- 1000000 #Capital de départ
Breakout <- strategy("Breakout")
portfolio.st <- account.st <- strat.st <- "Breakout"
if (!exists('.blotter')) .blotter <- new.env()
if (!exists('.strategy')) .strategy <- new.env()
initPortf(portfolio.st, #nom du book
symbols = symbols, #list des instruments
initDate=init.date, #date de départ du book
currency='USD') #devise de référence du book
initAcct(account.st, #nom du compte
portfolios = portfolio.st, #nom du portfeuille rattaché au compte
initDate = init.date, #date de départ du compte
currency = "USD", #devise du compte
initEq = initial.capital) #capital de départ du compte
initOrders(portfolio.st, #initialisation du container des orgers
initDate = init.date) #date de départ du book d'ordre
strategy("Breakout",store = TRUE)
#Definition des indicateurs
add.indicator("Breakout",
name = "DonchianChannel",
arguments=list(HL=quote(cbind(Hi(mktdata)[,1],Lo(mktdata)[,1])), n=20,include.lag=TRUE), label="Donchian20")
add.indicator("Breakout",
name = "DonchianChannel",
arguments=list(HL=quote(cbind(Hi(mktdata)[,1],Lo(mktdata)[,1])), n=10,include.lag=TRUE), label="Donchian10")
##Definition des signaux
add.signal("Breakout", #nom de la strategie
name="sigCrossover", #type de signal
arguments = list(columns =c("Close","high.Donchian20"), #liste des colonnes pour déterminer le signal
relationship="gt"), #type de relation du signal (sup ou égal, sup, inférieur etc..)
label = "long") #label de la colonne du signal
add.signal("Breakout", #nom de la strategie
name="sigCrossover", #type de signal
arguments = list(columns =c("Close","low.Donchian10"), #liste des colonnes pour déterminer le signal
relationship="lt"), #type de relation du signal (sup ou égal, sup, inférieur etc..)
label = "exitlong") #label de la colonne du signal
add.signal("Breakout", #nom de la strategie
name="sigCrossover", #type de signal
arguments = list(columns =c("Close","low.Donchian20"), #liste des colonnes pour déterminer le signal
relationship="lt"), #type de relation du signal (sup ou égal, sup, inférieur etc..)
label = "short")
add.signal("Breakout", #nom de la strategie
name="sigCrossover", #type de signal
arguments = list(columns =c("Close","high.Donchian10"), #liste des colonnes pour déterminer le signal
relationship="gt"), #type de relation du signal (sup ou égal, sup, inférieur etc..)
label = "exitshort") #label de la colonne du signal
#Limite
#addPosLimit( portfolio = "Breakout", # add position limit rules
# symbol = "AUDUSD",
# timestamp = init.date,
# maxpos = tradesize)
addPosLimit("Breakout","AUDUSD",maxpos = 1, minpos = -1,timestamp = as.POSIXct(init.date))
getPosLimit(portfolio = "Breakout","AUDUSD", timestamp = as.POSIXct(init.date))
##Definition des règles
add.rule("Breakout", #nom de la strategie
name = "ruleSignal", #
arguments = list(sigcol ="long", #nom de la colonne à vérifier
sigval = TRUE, #Application de la règle si signal
orderqty=tradesize, #taille de l'ordre
osFun = osMaxPos,
replace = FALSE,
ordertype = "market", #type d'ordre
orderside ="long"), #sens
type = "enter", #ouverture ou fermeture de pose
label = "Enterlong") #label si exécution
add.rule("Breakout", #nom de la strategie
name = "ruleSignal", #
arguments = list(sigcol ="exitlong", #nom de la colonne à vérifier
sigval = TRUE, #Application de la règle si signal
orderqty="all", #taille de l'ordre
replace = FALSE,
ordertype = "market", #type d'ordre
orderside ="long"), #sens
type = "exit", #ouverture ou fermeture de pose
label = "Exitlong") #label si exécution
add.rule("Breakout", #nom de la strategie
name = "ruleSignal", #
arguments = list(sigcol ="short", #nom de la colonne à vérifier
sigval = TRUE, #Application de la règle si signal
orderqty=-tradesize,#taille de l'ordre
replace = FALSE,
ordertype = "market", #type d'ordre
orderside ="short"), #sens
type = "enter", #ouverture ou fermeture de pose
label = "Entershort") #label si exécution
add.rule("Breakout", #nom de la strategie
name = "ruleSignal", #
arguments = list(sigcol ="exitshort", #nom de la colonne à vérifier
sigval = TRUE, #Application de la règle si signal
orderqty="all",#taille de l'ordre
osFun = osMaxPos,
replace = FALSE,
ordertype = "market", #type d'ordre
orderside ="short"), #sens
type = "exit", #ouverture ou fermeture de pose
label = "Exitshort") #label si exécution
out <- applyStrategy("Breakout", portfolios = portfolio.st)
回答1:
There are quite a few problems with your code. I'll try to explain all of them.
Initialization
You usually do not need to set initDate
in your calls to initPortf
, initAcct
, and initOrders
. Setting that value incorrectly can cause issues. So those calls should be:
initPortf(portfolio.st, #nom du book
symbols = symbols, #list des instruments
currency='USD') #devise de référence du book
initAcct(account.st, #nom du compte
portfolios = portfolio.st, #nom du portfeuille rattaché au compte
currency = "USD", #devise du compte
initEq = initial.capital) #capital de départ du compte
initOrders(portfolio.st) #initialisation du container des orgers
Position limits
You set max/min trade size to 1 in your call to addPosLimit
, but your trade size is 1 million. So any order will be rejected because it would put you over your position limit. You should also know that the timestamp
argument to addPosLimit
determines when the limits go into effect. If you always want them in effect, you should set the timestamp to a time before the first observation in your data. Also note that you only created position limits for AUDUSD
. You need to create position limits for each symbol.
addPosLimit("Breakout", "GBPUSD", maxpos = tradesize, timestamp = start(GBPUSD)-1)
addPosLimit("Breakout", "AUDUSD", maxpos = tradesize, timestamp = start(AUDUSD)-1)
addPosLimit("Breakout", "EURUSD", maxpos = tradesize, timestamp = start(EURUSD)-1)
Rules
One problem is that you passed osFun
to ruleSignal
. ruleSignal
does not have an osFun
argument. The argument is osFUN
(case matters). The other problem is that you specified osFun = osMaxPos
on your short exit rule, not the entry rule.
add.rule("Breakout", name = "ruleSignal",
arguments = list(sigcol = "long", #nom de la colonne à vérifier
sigval = TRUE, #Application de la règle si signal
orderqty = tradesize, #taille de l'ordre
osFUN = osMaxPos,
replace = FALSE,
ordertype = "market", #type d'ordre
orderside = "long"), #sens
type = "enter", label = "Enterlong")
add.rule("Breakout", name = "ruleSignal",
arguments = list(sigcol = "exitlong", #nom de la colonne à vérifier
sigval = TRUE, #Application de la règle si signal
orderqty = "all", #taille de l'ordre
replace = FALSE,
ordertype = "market", #type d'ordre
orderside = "long"), #sens
type = "exit", label = "Exitlong")
add.rule("Breakout", name = "ruleSignal",
arguments = list(sigcol = "short", #nom de la colonne à vérifier
sigval = TRUE, #Application de la règle si signal
orderqty = -tradesize,#taille de l'ordre
osFUN = osMaxPos,
replace = FALSE,
ordertype = "market", #type d'ordre
orderside = "short"), #sens
type = "enter", label = "Entershort")
add.rule("Breakout", name = "ruleSignal",
arguments = list(sigcol = "exitshort", #nom de la colonne à vérifier
sigval = TRUE, #Application de la règle si signal
orderqty = "all", #taille de l'ordre
replace = FALSE,
ordertype = "market", #type d'ordre
orderside = "short"), #sens
type = "exit", label = "Exitshort")
来源:https://stackoverflow.com/questions/41760247/limit-number-of-position-in-quantstrat