The script
A small library of risk helpers: position size from a stop, rounding to a step, a percent distance, and an exported type with a method. Paste it into a new library in the Pine Editor and publish it.
//@version=6
//@description Risk and price helpers: position size from a stop, rounding to a step, percent distance.
library("RiskTools")
//@function Units to trade so that a stop stopDistance away loses riskCash.
//@param riskCash Cash to risk, in the symbol's currency.
//@param stopDistance Distance from entry to stop, in price.
//@returns The quantity, or na when the stop distance isn't positive.
export qtyForRisk(float riskCash, float stopDistance) =>
stopDistance > 0 ? riskCash / (stopDistance * syminfo.pointvalue) : na
//@function Rounds a quantity down to a multiple of step (1 for whole shares).
//@param qty The quantity to round.
//@param step The smallest tradable increment.
//@returns The rounded quantity.
export roundDown(float qty, float step) =>
step > 0 ? math.floor(qty / step) * step : qty
//@function Percent distance from one price to another.
//@param fromPrice The reference price.
//@param toPrice The price to measure.
//@returns The distance in percent, or na when the reference is 0.
export pctChange(float fromPrice, float toPrice) =>
fromPrice != 0 ? (toPrice - fromPrice) / fromPrice * 100 : na
//@type A price level and the bar it was set on.
//@field price The level.
//@field barIdx The bar_index where it was set.
export type Level
float price
int barIdx
//@function Percent distance from the level to a price.
//@param lvl The level.
//@param price The price to measure.
//@returns The distance in percent.
export method distancePct(Level lvl, float price) =>
pctChange(lvl.price, price)
// Drawn only when the library itself is added to a chart, as a quick visual test
plot(pctChange(close[1], close), "Bar change %")How it works
library("RiskTools"). The title is also the name used in imports, so it must be an identifier: letters, digits and underscores, not starting with a digit.exportmakes a function, type or method visible to scripts that import the library. Everything else (helpers, the testplot()) stays private.- Typed parameters. In an exported function every parameter needs a type (
float riskCash). Qualifierssimpleandseriesare allowed; the function's body can't depend oninput.*()calls or on global variables, but it can use built-ins such assyminfo.pointvalue. - Annotations.
//@description,//@function,//@param,//@returns,//@typeand//@fieldcomments are shown in the library's documentation and in the Pine Editor's autocomplete for people who import it. - The exported type and method.
LevelanddistancePct()are used in the importing script asrt.Level.new(...)andlastLow.distancePct(close): the alias prefixes the type, and a method is called on the object. - Publishing. In the Pine Editor, publish the library (a private publication is enough for your own scripts). Each new publication increments the version number.
Importing the library
Once RiskTools is published, an indicator imports it by your username, its name and its version. This script only compiles after you publish the library and replace YourUsername with your TradingView username.
//@version=6
indicator("Risk per trade (library demo)", overlay = true)
// Replace YourUsername with the TradingView username that published RiskTools, and 1 with its current version
import YourUsername/RiskTools/1 as rt
riskCash = input.float(100, "Cash to risk per trade (symbol currency)", minval = 1)
atrMult = input.float(2, "Stop distance (x ATR)", minval = 0.5, step = 0.5)
qtyStep = input.float(1, "Quantity step", minval = 0)
float stopDist = atrMult * ta.atr(14)
float qty = rt.roundDown(rt.qtyForRisk(riskCash, stopDist), qtyStep)
pl = ta.pivotlow(low, 5, 5)
var rt.Level lastLow = rt.Level.new(na, na)
if not na(pl)
lastLow := rt.Level.new(pl, bar_index - 5)
plot(close - stopDist, "Long stop", color.red)
plot(qty, "Quantity for the risk", display = display.data_window)
plot(lastLow.distancePct(close), "% above the last swing low", display = display.data_window)Pitfalls
- Importing before publishing. An import only works for a published library, with its exact username, name and version. A typo in the import line, or an alias you don't use when calling, leaves the functions unknown (Could not find function or function reference).
- Untyped parameters.
export qtyForRisk(riskCash, stopDistance) =>doesn't compile in a library: every exported parameter needs a type. - Inputs and globals in exported code. An exported function can't depend on
input.*()calls or on a non-constant global variable. Pass the values as parameters. Only constants can be exported as values, withexport const. - Versions don't update themselves.
import YourUsername/RiskTools/1keeps using version 1 after you publish version 2. Change the number in each importing script when you want the update. - Visibility. Libraries are always open source, and a script published publicly can only import public libraries. Keep anything you don't want to share out of them.
Variations
Constants. export const float RISK_DEFAULT = 1.0 exports a value; importers read it as rt.RISK_DEFAULT. Allowed types are int, float, bool, color and string.
Data requests in a library. An exported function can call request.security() only if the library is declared with library("Name", dynamic_requests = true), and the requested expression can't depend on the function's parameters (the symbol and timeframe can).
Not ready to publish? Keep the functions at the top of each script that uses them, as in the functions and methods example, and move them to a library once they've settled.
Questions
Do I have to publish a Pine Script library to use it?
Yes. A script can only import a published library. If you don't want it public, publish it privately: your own scripts can import private libraries, but public scripts can only import public ones.
Do scripts get library updates automatically?
No. The import line names a version, such as import YourUsername/RiskTools/1 as rt, and the script keeps using that version until you change the number.
Can a Pine Script library export variables?
Only constants, declared with export const and an int, float, bool, color or string type. Anything that changes from bar to bar has to be returned by an exported function instead.
Related pages
Every script on this page was checked with Edgoro Pine Check (Pine Script v6 rules). Pine Check is a static checker, not TradingView's compiler: TradingView compiles the script when you save it in the Pine Editor. The scripts are examples to learn from, not trading systems. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.