For my own future reference, and for anyone else who needs it.
Pine script strategy code can be confusing and awkward, so I finally sat down and had a little think about it and put something together that actually works (i think...)
Code is commented where I felt might be necessary (pretty much everything..) and covers:
- Take Profit
- Stop Loss
- Trailing Stop
- Trailing Stop Offset
Also shows how to use functions (or variables/series) to execute trade entries and exits.
//@version=2 strategy(title = "Strategy Code Example", shorttitle = "Strategy Code Example", overlay = true, pyramiding = 0, default_qty_type = strategy.percent_of_equity, default_qty_value = 10, currency = currency.GBP) // Revision: 1 // Author: @JayRogers // // *** THIS IS JUST AN EXAMPLE OF STRATEGY RISK MANAGEMENT CODE IMPLEMENTATION *** // === GENERAL INPUTS === // short ma maFastSource = input(defval = open, title = "Fast MA Source") maFastLength = input(defval = 14, title = "Fast MA Period", minval = 1) // long ma maSlowSource = input(defval = open, title = "Slow MA Source") maSlowLength = input(defval = 21, title = "Slow MA Period", minval = 1) // === STRATEGY RELATED INPUTS === tradeInvert = input(defval = false, title = "Invert Trade Direction?") // the risk management inputs inpTakeProfit = input(defval = 1000, title = "Take Profit", minval = 0) inpStopLoss = input(defval = 200, title = "Stop Loss", minval = 0) inpTrailStop = input(defval = 200, title = "Trailing Stop Loss", minval = 0) inpTrailOffset = input(defval = 0, title = "Trailing Stop Loss Offset", minval = 0) // === RISK MANAGEMENT VALUE PREP === // if an input is less than 1, assuming not wanted so we assign 'na' value to disable it. useTakeProfit = inpTakeProfit >= 1 ? inpTakeProfit : na useStopLoss = inpStopLoss >= 1 ? inpStopLoss : na useTrailStop = inpTrailStop >= 1 ? inpTrailStop : na useTrailOffset = inpTrailOffset >= 1 ? inpTrailOffset : na // === SERIES SETUP === /// a couple of ma's.. maFast = ema(maFastSource, maFastLength) maSlow = ema(maSlowSource, maSlowLength) // === PLOTTING === fast = plot(maFast, title = "Fast MA", color = green, linewidth = 2, style = line, transp = 50) slow = plot(maSlow, title = "Slow MA", color = red, linewidth = 2, style = line, transp = 50) // === LOGIC === // is fast ma above slow ma? aboveBelow = maFast >= maSlow ? true : false // are we inverting our trade direction? tradeDirection = tradeInvert ? aboveBelow ? false : true : aboveBelow ? true : false // === STRATEGY - LONG POSITION EXECUTION === enterLong() => not tradeDirection and tradeDirection // functions can be used to wrap up and work out complex conditions exitLong() => tradeDirection and not tradeDirection strategy.entry(id = "Long", long = true, when = enterLong()) // use function or simple condition to decide when to get in strategy.close(id = "Long", when = exitLong()) // ...and when to get out // === STRATEGY - SHORT POSITION EXECUTION === enterShort() => tradeDirection and not tradeDirection exitShort() => not tradeDirection and tradeDirection strategy.entry(id = "Short", long = false, when = enterShort()) strategy.close(id = "Short", when = exitShort()) // === STRATEGY RISK MANAGEMENT EXECUTION === // finally, make use of all the earlier values we got prepped strategy.exit("Exit Long", from_entry = "Long", profit = useTakeProfit, loss = useStopLoss, trail_points = useTrailStop, trail_offset = useTrailOffset) strategy.exit("Exit Short", from_entry = "Short", profit = useTakeProfit, loss = useStopLoss, trail_points = useTrailStop, trail_offset = useTrailOffset)
strategy.entry(id = "Long", long = true, when = enterLong()) // use function or simple condition to decide when to get in
strategy.close(id = "Long", when = exitLong()) // ...and when to get out
Im having a little trouble with the script because it duplicates some trades. Does any one know how to fix it?
I find it gives a false value for the exit. If the trailing stop is triggered, it reports the trade close as either high or low of the bar, seemingly depending if you are long or short - giving wildly succesful backtest results , but false ones.
Anyone else get this?
strategy.exit("Exit long", from_entry="Long", qty = 20, stop = (close-R_value), comment = "xxx"
The problem is, say I pyramid entered in 3 times 20 shares, but only one of the pyramid entries satisfies the stop condition. The List of Trades will show all 3 pyramid entries were exited. However on the plot, it will only show one -20 qty "xxx" exit.
With trail_points and trail_offset, it is the same problem exiting the entire set of pyramid buys.
In addition with trail_points and _trail_offset, either I'm not understanding what these two parameters mean, or it's not calculating it right. I understand it as this: strategy.exit context: trail_points = 1000, trail_offset=200. As: once position is up 10%, it will sell if it then falls 2%. Can someone shed light on if this understanding is correct?
Hope this helps
Tick is 0.01 in JPY and stocks. But what is a tick in crypto I wonder till this same moment.... is it 0.00000001 ?
And yes, still trying to understand how it all maps to crypto.
or you can ctrl-left-click on any function/variable in the PineEditor code window - it will bring up a built-in documentation window which can co-exist with the editor. Search for strategy.exit() for explanation of the trailing_points parameter as follows:
- trail_points (float) An optional parameter. Trailing stop activation level (profit specified in ticks). ...
For ticks I use syminfo.mintick in the code to correctly determine the ticks. Suppose I have a SL = high-low, then in ticks this will be SL/syminfo.mintick.
Hope this helps.
PS. I cannot make the trailing stop working for me, I think TD has implemented a slightly different concept of the trailing than generally taught, and I lack understanding thereof. I am missing what the tail_point as in stop activation level is and what is it for, as well as trail_offset?
In my mind I want to start trailing immediately with a specified SL=Y a soon as I call strategy.entry(). Or suppose I want to start trailing with Sl=Y as soon as I moved up (or down) an amount X with the Sl=Y
Can anyone give me an example that works?
In this example, I use price rather points parameters, with NaN (default) trail_offset:
stop_loss = 3*atr(5)
stop_price_buy = close - stop_loss //my stop loss price for long
strategy.exit("Exit Buy", from_entry="Buy", stop=stop_price_buy, trail_price=stop_price_buy, comment="Exit Buy SL")
My idea is I want to start trailing from the level of the initial stop loss. And the code opens and immediately closes the order , so i think I don't quite capture how to use these parameters.
In this example I use ticks rather than price
stop_loss = 3*atr(5)
strategy.exit("Exit Buy", from_entry="Buy", loss=stop_loss/syminfo.mintick, trail_points=stop_loss/syminfo.mintick, trail_offset=0, comment="Exit Buy SL")
Bu the effect is that the price moves up for the stop_loss number of ticks and takes profit, closes the order which is not what I want at all. SO I am a little confused and have to spend time experimenting with it further.