Strategy Development
Creating and testing trading strategies with PyneCore
Strategy Development with PyneCore
This guide introduces you to creating and testing trading strategies using PyneCore. As PyneCore maintains full compatibility with Pine Script’s strategy functionality, this document focuses on the basics with links to TradingView’s official documentation for detailed reference.
Creating a Strategy
In PyneCore, creating a strategy starts with a script decorated with @script.strategy
:
"""
@pyne
"""
from pynecore import Series, Persistent
from pynecore.lib import script, close, ta, strategy
@script.strategy("Simple MA Crossover", overlay=True)
def main():
# Strategy logic here
fast_ma = ta.sma(close, 9)
slow_ma = ta.sma(close, 21)
# Generate signals
if ta.crossover(fast_ma, slow_ma):
strategy.entry("Long", strategy.long)
if ta.crossunder(fast_ma, slow_ma):
strategy.close("Long")
The @script.strategy
decorator accepts numerous parameters to configure backtest settings:
@script.strategy(
"Advanced Strategy Settings",
initial_capital=10000, # Starting capital
commission_type=strategy.commission.percent, # Commission type
commission_value=0.1, # Commission value (0.1%)
pyramiding=1, # Max number of entries in same direction
default_qty_type=strategy.percent, # Position sizing method
default_qty_value=10, # Size value (10% of equity)
)
Configuration with TOML Files
One of the powerful features of PyneCore is that strategy settings can be modified without changing the code. When you run a strategy, PyneCore automatically generates a .toml
configuration file with the same base name as your strategy script. For example, if your strategy is mystrategy.py
, PyneCore will create mystrategy.toml
.
This TOML file contains all strategy settings and input parameters, allowing you to:
- Change strategy parameters (like
initial_capital
orcommission_value
) - Modify input values
- Enable/disable specific settings
Example TOML file structure:
# Indicator / Strategy / Library Settings
[script]
initial_capital = 10000
commission_value = 0.1
pyramiding = 1
# Add more settings here...
# Input Settings
[inputs.fast_length]
# Input metadata, cannot be modified
# input_type: "int"
# defval: 9
# title: "Fast MA Length"
# minval: 1
# Change here to modify the input value
value = 12
Simply edit this file and run your strategy again - PyneCore will use the updated values without requiring any code changes. This is extremely useful for:
- Testing different parameter combinations
- Optimizing strategies
- Running the same strategy with different settings for various markets
Strategy Entry and Exit
Entering Positions
# Long entry
strategy.entry("Long", strategy.long)
# Short entry
strategy.entry("Short", strategy.short)
# Entry with specific amount
strategy.entry("Long", strategy.long, qty=2)
Exiting Positions
# Close specific entry
strategy.close("Long")
# Close all positions
strategy.close_all()
# Exit with profit/loss targets
strategy.exit("Exit", "Long", profit=100, loss=50)
For more detailed information on entries and exits, refer to Pine Script strategy.entry and strategy.exit.
Position Sizing
PyneCore supports various position sizing methods:
# Fixed size (specific quantity)
@script.strategy("Fixed Size", default_qty_type=strategy.fixed, default_qty_value=1)
# Percentage of equity
@script.strategy("Percent of Equity", default_qty_type=strategy.percent, default_qty_value=10)
# Cash amount
@script.strategy("Cash Amount", default_qty_type=strategy.cash, default_qty_value=1000)
You can also dynamically size positions within your strategy:
# Dynamic position sizing based on ATR
atr_value = ta.atr(14)
risk_amount = 500 # Risk $500 per trade
qty = risk_amount / atr_value
strategy.entry("Long", strategy.long, qty=qty)
Strategy Properties
PyneCore provides access to various strategy properties through the strategy
module:
from pynecore.lib import strategy
# Current position info
current_position = strategy.position_size
# Account info
current_equity = strategy.equity
# Trade info
if strategy.opentrades > 0:
entry_price = strategy.opentrades.entry_price(0)
entry_time = strategy.opentrades.entry_time(0)
Example Strategies
Simple Moving Average Crossover
"""
@pyne
"""
from pynecore import Series
from pynecore.lib import script, close, ta, strategy, plot, color
@script.strategy("MA Crossover Strategy", overlay=True)
def main(
fast_length: int = input.int(9, title="Fast MA Length", minval=1),
slow_length: int = input.int(21, title="Slow MA Length", minval=1)
):
# Calculate indicators
fast_ma: Series[float] = ta.sma(close, fast_length)
slow_ma: Series[float] = ta.sma(close, slow_length)
# Generate signals
buy_signal = ta.crossover(fast_ma, slow_ma)
sell_signal = ta.crossunder(fast_ma, slow_ma)
# Execute strategy
if buy_signal:
strategy.entry("Long", strategy.long)
elif sell_signal:
strategy.close("Long")
# Visualization
plot(fast_ma, "Fast MA", color=color.blue)
plot(slow_ma, "Slow MA", color=color.red)
RSI Mean Reversion Strategy
"""
@pyne
"""
from pynecore import Series
from pynecore.lib import script, close, ta, strategy, plot, color
@script.strategy("RSI Mean Reversion", overlay=True)
def main(
rsi_length: int = input.int(14, title="RSI Length", minval=1),
overbought: int = input.int(70, title="Overbought Level"),
oversold: int = input.int(30, title="Oversold Level")
):
# Calculate RSI
rsi_value: Series[float] = ta.rsi(close, rsi_length)
# Generate signals
buy_signal = ta.crossover(rsi_value, oversold)
sell_signal = ta.crossunder(rsi_value, overbought)
# Execute strategy
if buy_signal:
strategy.entry("Long", strategy.long)
elif sell_signal:
strategy.close("Long")
# Return RSI plot (shown in separate pane)
return {
"RSI": rsi_value,
"Overbought": overbought,
"Oversold": oversold
}
Backtesting with PyneCore
PyneCore’s strategy backtesting functionality mirrors Pine Script’s, providing:
- Performance metrics
- Trade simulation
- Position management
- Commission modeling
- Equity curve calculation
To run a backtest using PyneCore’s CLI:
pyne run mystrategy.py data/eurusd_daily.ohlcv
This executes your strategy on the provided price data and generates backtest results in the output directory.
While PyneCore’s backtesting capabilities are already powerful and Pine Script-compatible, future versions will offer enhanced analysis and visualization tools designed specifically for Python users.
Best Practices
1. Mind the Look-Ahead Bias and Indexing
Ensure your strategy only uses data that would have been available at the time of the trading decision. In PyneCore, similar to Pine Script, indices refer to historical data where larger indices indicate older bars:
current = close[0] # Current bar (or just `close`)
previous = close[1] # One bar ago
older = close[10] # Ten bars ago
Note that PyneCore does not support negative indices - attempting to use them (like close[-1]
) will raise an IndexError
as there’s no way to reference future data in the backtest.
2. Test Strategy Robustness
- Test on multiple symbols and timeframes
- Vary strategy parameters to avoid over-optimization
- Include different market conditions in test data
3. Start Simple
Begin with simpler strategies before adding complexity:
- Start with basic entry and exit conditions
- Add position sizing after ensuring the base strategy works
- Gradually incorporate filters and additional conditions
- Add risk management logic
Further Resources
As PyneCore continues to evolve, additional strategy development features and backtesting capabilities will be added. The project welcomes community contributions to enhance these capabilities further while maintaining full compatibility with Pine Script.