Your First PyneCore Script
Learn how to write and run your first PyneCore script
Your First PyneCore Script
This guide will walk you through creating and running your first PyneCore script. You’ll learn the basic structure of a Pyne script and see how it differs from regular Python.
The Magic Comment
Every PyneCore script must start with a special magic comment to identify it as a Pyne script:
"""
@pyne
"""
This comment must be placed at the beginning of your file, before any import statements. It tells the PyneCore system to apply the necessary AST transformations to make your Python code behave like Pine Script.
Basic Script Structure
A minimal PyneCore script has the following structure:
"""
@pyne
"""
from pynecore.lib import script, close
@script.indicator("My First Indicator")
def main():
# Your code goes here
return {"close": close}
Let’s break this down:
- Magic Comment: Signals that this is a Pyne script
- Imports: Import necessary modules from PyneCore
- Script Declaration: Use a decorator to define the script type (indicator, strategy, etc.)
- Main Function: The entry point of your script that will be executed for each bar
Creating a Simple Moving Average Indicator
Let’s create a simple indicator that calculates and plots a 20-period Simple Moving Average (SMA):
"""
@pyne
"""
from pynecore import Series
from pynecore.lib import script, close, ta, plot, color
@script.indicator("Simple Moving Average", overlay=True)
def main():
# Calculate 20-period SMA
sma = ta.sma(close, 20)
# Plot the SMA on the chart (PyneCore won't plot anything, it just saves the data)
plot(sma, "SMA")
Save this code to a file named simple_ma.py
in your working directorys scripts/
folder.
Download some data
This will download the OHLCV data for the BTC/USDT pair from Bybit and save it as ccxt_BYBIT_BTC_USDT_USDT_1D.ohlcv
in your working directorys data/
folder:
pyne data download ccxt --symbol "BYBIT:BTC/USDT:USDT"
Running Your Script
To run your PyneCore script, use the command-line interface:
pyne run simple_ma ccxt_BYBIT_BTC_USDT_USDT_1D.ohlcv
This will run your script on every bar of the OHLCV data, and save the plots or returned values to the output folder of your working directory. This mechanism is the heart of PyneCore. You actually write a script that will run on every candle.
Adding Parameters
Let’s enhance our script by adding user-configurable parameters:
"""
@pyne
"""
from pynecore import Series
from pynecore.lib import script, close, ta, plot, color, input
@script.indicator("Customizable Moving Average", overlay=True)
def main():
# Input parameters
length = input.int("Period", 20, minval=1)
ma_type = input.string("Type", "SMA", options=["SMA", "EMA", "WMA"])
line_color = input.color("Line Color", color.blue)
# Calculate the selected moving average
ma: Series[float] = None
if ma_type == "SMA":
ma = ta.sma(close, length)
elif ma_type == "EMA":
ma = ta.ema(close, length)
else: # WMA
ma = ta.wma(close, length)
# Plot the result
plot(ma, f"{ma_type} ({length})", color=line_color, linewidth=2)
PyneCore will save a toml file in the output folder which contains the parameters of your script. If you would like to change a parameter, you can do so by removing the comment from the line and changing the default value.
Understanding Series and Persistence
Two key concepts in PyneCore are Series and Persistent variables:
Series Variables
A Series variable holds a time series of values, with one value per bar:
"""
@pyne
"""
from pynecore import Series
from pynecore.lib import script, close, high, low, ta, plot, color
@script.indicator("Series Example", overlay=True)
def main():
# Series variables
price: Series[float] = close
highest: Series[float] = ta.highest(high, 10)
lowest: Series[float] = ta.lowest(low, 10)
# Series operations
middle = (highest + lowest) / 2
# Accessing historical values
prev_price = price[1] # Previous bar's price
# Plot results
plot(middle, "Middle", color=color.purple)
In Pyne code you can declare a Series by adding a Series
type annotation, but you don’t need to actually create a Series object. More about Series here.
Persistent Variables
Persistent variables retain their values between bars:
"""
@pyne
"""
from pynecore import Series, Persistent
from pynecore.lib import script, close, plot, color
@script.indicator("Persistent Example", overlay=True)
def main():
# Persistent variable - retains its value from bar to bar
counter: Persistent[int] = 0
counter += 1
# Persistent with series operations
sum_price: Persistent[float] = 0
sum_price += close
avg_price = sum_price / counter
# Plot
plot(avg_price, "Average Price", color=color.orange)
More about Persistent variables here.
Creating a Complete Strategy
Let’s create a simple trading strategy using PyneCore:
"""
@pyne
"""
from pynecore import Series
from pynecore.lib import script, close, ta, strategy, plot, color
@script.strategy("Simple Crossover Strategy", overlay=True)
def main():
# Calculate fast and slow moving averages
fast_ma: Series[float] = ta.ema(close, 9)
slow_ma: Series[float] = ta.ema(close, 21)
# Define entry conditions
buy_signal = ta.crossover(fast_ma, slow_ma)
sell_signal = ta.crossunder(fast_ma, slow_ma)
# Execute the strategy
if buy_signal:
strategy.entry("Long", strategy.long)
elif sell_signal:
strategy.entry("Short", strategy.short)
# Plot indicators
plot(fast_ma, "Fast EMA", color=color.blue)
plot(slow_ma, "Slow EMA", color=color.red)
Working with Functions
You can define your own functions in PyneCore:
"""
@pyne
"""
from pynecore import Series
from pynecore.lib import script, close, plot, color, math
def average(a, b):
return (a + b) / 2
def custom_ma(src, length):
"""A simple moving average implementation"""
sum = 0.0
for i in range(length):
sum += src[i]
return sum / length
@script.indicator("Custom Functions", overlay=True)
def main():
# Use custom functions
avg = average(close, close[1])
custom_average: Series[float] = custom_ma(close, 20)
# Plot results
plot(avg, "Bar Average", color=color.green)
plot(custom_average, "Custom MA", color=color.purple)
You could also use inline functions, if you need variables from outer scopes. Learn more about how functions work in PyneCore in the Function Isolation and Advanced Function Isolation documentation.
Next Steps
Now that you’ve created your first PyneCore script, you can:
- Learn how to convert existing Pine Script code to PyneCore
- Explore the core concepts of PyneCore in depth
- Check out the library documentation for available functions and indicators
- Dive into advanced topics for more technical details