Pynescript#
Features#
Handle Pinescript using Python
Parse Pinescript code into AST
Dump parsed AST
Unparse parsed AST back to Pinescript code
Given an example pinescript with name of rsi_strategy.pine:
//@version=5
strategy("RSI Strategy", overlay=true)
length = input( 14 )
overSold = input( 30 )
overBought = input( 70 )
price = close
vrsi = ta.rsi(price, length)
co = ta.crossover(vrsi, overSold)
cu = ta.crossunder(vrsi, overBought)
if (not na(vrsi))
if (co)
strategy.entry("RsiLE", strategy.long, comment="RsiLE")
if (cu)
strategy.entry("RsiSE", strategy.short, comment="RsiSE")
//plot(strategy.equity, title="equity", color=color.red, linewidth=2, style=plot.style_areabr)
Parsing script into AST and dumping it:
$ pynescript parse-and-dump rsi_strategy.pine
Gives like:
Script(
body=[
Expr(
value=Call(
func=Name(
id='strategy',
),
arguments=[
Argument(
value=Constant(
value='RSI Strategy',
),
name=None,
),
Argument(
value=Constant(
value=True,
),
name='overlay',
),
],
type_argument=None,
),
),
Assign(
target='length',
value=Call(
func=Name(
id='input',
),
arguments=[
Argument(
value=Constant(
value=14,
),
name=None,
),
],
type_argument=None,
),
declaration_mode=None,
type_specifier=None,
),
...
Full AST dump that is quote long...
Script(
body=[
Expr(
value=Call(
func=Name(
id='strategy',
),
arguments=[
Argument(
value=Constant(
value='RSI Strategy',
),
name=None,
),
Argument(
value=Constant(
value=True,
),
name='overlay',
),
],
type_argument=None,
),
),
Assign(
target='length',
value=Call(
func=Name(
id='input',
),
arguments=[
Argument(
value=Constant(
value=14,
),
name=None,
),
],
type_argument=None,
),
declaration_mode=None,
type_specifier=None,
),
Assign(
target='overSold',
value=Call(
func=Name(
id='input',
),
arguments=[
Argument(
value=Constant(
value=30,
),
name=None,
),
],
type_argument=None,
),
declaration_mode=None,
type_specifier=None,
),
Assign(
target='overBought',
value=Call(
func=Name(
id='input',
),
arguments=[
Argument(
value=Constant(
value=70,
),
name=None,
),
],
type_argument=None,
),
declaration_mode=None,
type_specifier=None,
),
Assign(
target='price',
value=Name(
id='close',
),
declaration_mode=None,
type_specifier=None,
),
Assign(
target='vrsi',
value=Call(
func=Attribute(
value=Name(
id='ta',
),
attribute='rsi',
),
arguments=[
Argument(
value=Name(
id='price',
),
name=None,
),
Argument(
value=Name(
id='length',
),
name=None,
),
],
type_argument=None,
),
declaration_mode=None,
type_specifier=None,
),
Assign(
target='co',
value=Call(
func=Attribute(
value=Name(
id='ta',
),
attribute='crossover',
),
arguments=[
Argument(
value=Name(
id='vrsi',
),
name=None,
),
Argument(
value=Name(
id='overSold',
),
name=None,
),
],
type_argument=None,
),
declaration_mode=None,
type_specifier=None,
),
Assign(
target='cu',
value=Call(
func=Attribute(
value=Name(
id='ta',
),
attribute='crossunder',
),
arguments=[
Argument(
value=Name(
id='vrsi',
),
name=None,
),
Argument(
value=Name(
id='overBought',
),
name=None,
),
],
type_argument=None,
),
declaration_mode=None,
type_specifier=None,
),
Expr(
value=If(
condition=Unary(
operator=Not(),
operand=Call(
func=Name(
id='na',
),
arguments=[
Argument(
value=Name(
id='vrsi',
),
name=None,
),
],
type_argument=None,
),
),
body=[
Expr(
value=If(
condition=Name(
id='co',
),
body=[
Expr(
value=Call(
func=Attribute(
value=Name(
id='strategy',
),
attribute='entry',
),
arguments=[
Argument(
value=Constant(
value='RsiLE',
),
name=None,
),
Argument(
value=Attribute(
value=Name(
id='strategy',
),
attribute='long',
),
name=None,
),
Argument(
value=Constant(
value='RsiLE',
),
name='comment',
),
],
type_argument=None,
),
),
],
orelse=None,
),
),
Expr(
value=If(
condition=Name(
id='cu',
),
body=[
Expr(
value=Call(
func=Attribute(
value=Name(
id='strategy',
),
attribute='entry',
),
arguments=[
Argument(
value=Constant(
value='RsiSE',
),
name=None,
),
Argument(
value=Attribute(
value=Name(
id='strategy',
),
attribute='short',
),
name=None,
),
Argument(
value=Constant(
value='RsiSE',
),
name='comment',
),
],
type_argument=None,
),
),
],
orelse=None,
),
),
],
orelse=None,
),
),
],
version=5,
)
Parsing into AST and unparsing it back:
$ pynescript parse-and-unparse rsi_strategy.pine
Gives (with some difference in syntax including spacing):
//@version=5
strategy("RSI Strategy", overlay=true)
length = input(14)
overSold = input(30)
overBought = input(70)
price = close
vrsi = ta.rsi(price, length)
co = ta.crossover(vrsi, overSold)
cu = ta.crossunder(vrsi, overBought)
if not na(vrsi)
if co
strategy.entry("RsiLE", strategy.long, comment="RsiLE")
if cu
strategy.entry("RsiSE", strategy.short, comment="RsiSE")
Future Plans#
Tradingview-less standalone local back-testing and live-trading using NautilusTrader
Requirements#
Python 3.8 or higher
Installation#
You can install Pynescript via pip from PyPI:
$ pip install pynescript
Usage#
Please see the Usage for details.
Also check out example_usage.py script for examples.
Contributing#
Contributions are very welcome. To learn more, see the Contributor Guide.
License#
Distributed under the terms of the LGPL 3.0 license, Pynescript is free and open source software.
Issues#
If you encounter any problems, please file an issue along with a detailed description.
Credits#
This project was generated from @cjolowicz’s Hypermodern Python Cookiecutter template.