Pynescript#

PyPI Status Python Version License

Read the documentation at https://pynescript.readthedocs.io/ Tests Codecov

pre-commit Black

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#

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.