Ciao, se sei qui è perché vuoi iniziare a imparare a programmare su TradingView, il linguaggio di programmazione utilizzato sulla piattaforma è PineScript. Quindi benvenuto in questa prima Guida PineScript – 01.
Mi presento, sono Drilon e sono un programmatore con la passione per la finanza personale, questo è il mio blog dove racconto il mio percorso e provo a spiegare ciò che imparo nel mentre.
Dove si programma?
Il primo step sicuramente è quello di capire dove si programma su TradingView, basterà cliccare nel pulsante PineEditor, come nella figura sotto
A questo punto si aprirà una nuova tab sotto, dove forse c’è del codice d’esempio che comunque non ci interessa. Dovremmo andare a destra e cliccare su Open
Da qui possiamo notare diverse voci,
My Script -> ci fa vedere gli script già scritti
Build-in script -> apre degli indicatori già scritti
New Indicator -> ci permette di creare un nuovo indicatore
New Strategy -> ci permette di creare una strategia automatizzata con tanto di backtest e statistiche
New Libray -> permette di creare delle librerie riutilizzabili… lascia perdere per ora
Clicchiamo su New Indicator e avremo questo codice
//@version=5
indicator("My script")
plot(close)
Analizziamolo insieme:
//@version=5
Indica la versione di PineScript utilizzata per scrivere l’indicatore, da una versione all’altra possono cambiare alcuni comandi.
indicator("My script")
Impostiamo il nome che vogliamo dare al nostro indicatore
plot(close)
Il comando plot è utilizzato per “disegnare” / “stampare” a schermo qualcosa, in questo caso il prezzo di chiusura
Proviamo a salvarlo e cliccare “Add to chart” sempre dal pannello in alto a destra
Wow, abbiamo appena creato un indicatore! Poco utile, però è un inizio 😀
Piano piano impareremo a creare tutti gli indicatori che vogliamo e strategie automatiche per migliorare il nostro trading! Se questa prima Guida PineScript – 01 ti è piaciuta ti consiglio di continuare con il resto!
Profitti da capogiro e equityline bellissima! Ma non è tutto oro ciò che luccica, ecco perché questa è una strategia che inganna.
Ciao, sono Drilon e sono un programmatore con la passione per la finanza personale, in questo blog condivido il mio percorso.
Questa è una strategia che all’apparenza è potentissima però bisogna sapere cosa c’è sotto per valutare al meglio.
La logica che c’è sotto è: COMPRA quando il macd incrocia dal basso verso l’alto, fine!
Molto semplice ma già da qui si può intuire che se si utilizza su un asset che non cresce sempre il profitto va a quel paese.
In questo caso è stata applicata all’SP500 che sappiamo che cresce sempre da più di 100 anni “per struttura” (è l’andamento del mercato, l’uomo crea valore sempre, se non fosse così vorrebbe dire che come specie si andrebbe a peggiorare, ma questo è tutto un altro discorso).
Quindi questa strategia è efficace? SI MA non hai bisogno di questa strategia per fare una cosa del genere, alla fine è un PAC (Piani d’accumulo).
Questo è un esempio su BITCOIN
Ma vediamo su un asset più volatile come Palantir (PLTR)
Na merda! Ma questo perchè? Perché Palantir è stata listata, è andata per un paio di mesi verso l’alto e poi è crollata, quindi le posizioni sono tutte in negativo, poi magari tra 10 anni Palantir sarà la nuova Apple, però chi lo può sapere?!
Proprio questo è il problema, quindi tanto vale fare un PAC autonomamente.
Questo era un esempio del perché è importante capire come funziona una strategia, non si può applicare a tutto ed è un attimo perdere soldi. Attenzione alla strategia che inganna!
Sei alla ricerca di corsi gratuiti per imparare a programmare o sulla finanza? Magari unire entrambe le cose?
Ciao sono Drilon e sono un programmatore con la passione per la finanza personale, in questo blog racconto il mio percorso finanziario.
Torniamo a te, vuoi dei corsi gratuiti eccoli qui.
Basilari
Financial Markets
Corso tenuto da Shiller, premio Nobel per l’economia, all’università di Yale. Introduce in maniera gentile argomenti fondamentali per iniziare a capire i mercati finanziari
Corso sempre dell’MIT che tratta distribuzioni di probabilità, analisi di serie storiche, ottimizzazione, simulazione Monte Carlo e processi stocastici
Offerto dalla Caltech, questo corso vi introdurrà al pricing delle opzioni nel discreto e nel continuo. Vi fornirà le basi per poter eventualmente continuare ad approfondire il pricing dei derivati
Un’introduzione leggera ai modelli sui tassi d’interesse. Utile per capire la curva dei tassi, rischiosità dei bond, arbitrage, pricing theory, pricing di derivate
Serie di quatto corsi fondamentali offerti dalla Columbia University che trattano di ottimizzazione di portafoglio, struttura dei tassi d’interesse e derivate
Corso fondamentale per studiare l’ottimizzazione convessa. Per esempio, è fondamentale per applicare ed implementare i modelli di asset allocation nella vita reale
Serie di lezioni/codici curata da Tom Sargent, premio Nobel per l’economia, in cui si parla di Python, economia quantitativa, data science, markow chain e Julia
Ciao, oggi ti parlo di una delle strategie più semplici che ci siano, ovvero l’intersezione di due Medie Mobili Esponenziali (EMA).
Ciao sono Drilon e sono un programmatore con la passione per la finanza personale, questo è il mio blog dove racconto il mio percorso.
Idea di base
L’idea di base della strategia è quella di aprire un ordine BUY quando l’ema a breve termine va sopra l’ema a lungo termine, aprire un ordine SEL quando l’ema a breve termine va sotto l’ema a lungo termine.
All’apertura di un ordine si chiude l’ordine nel verso opposto!
Processo
Partendo dall’ottimizzazione dei parametri in un periodo che va dal 2019 al 2023 trovo le migliori combinazioni in questo lasso di tempo. Dopodiché la testo in un range più ampio che va dal 2011 al 2023.
Se in entrambe le situazioni la strategia si comporta bene ed ha un andamento che reputo valido a quel punto la metto in live.
Ottimizzazione
Ottimizzazione
Questo è quello che ho ottenuto dall’ottimizzazione, un andamento abbastanza costante.
L’ottimizzazione l’ho fatta sul timeframe, e le lunghezze delle due ema. Volendo si può mettere un filtro temporale sulle ore e vedere in che range di tempo conviene operare (Next step).
Backtest
backtest
Questo è il risultato del backtest dal 2011 al 2023! Non è male un 35% di profitto (ho aumentato i lotti rispetto all’ottimizzazione)
Non ha nemmeno un drawdown eccessivo però l’andamento non mi convince, non è costante. Si nota che nei primi 90 ordini non si comporta bene. Il prossimo step sarebbe quello di andare a vedere il grafico e vedere cosa è successo in quei 90 ordini.
In questo modo possiamo trovare qualcosa per migliorare la strategia.
Conclusione
Personalmente non è una strategia che mi convince e che metterei in live, ci si può lavorare però per com’è ora assolutamente no. Il problema è che il mercato ovviamente non si comporta sempre allo stesso modo, quindi è veramente difficile trovare un setup di medie mobili che funzioni sempre.
Codice
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class IIScalping : Robot
{
[Parameter("Source", Group = "Data series")]
public DataSeries Source { get; set; }
[Parameter(DefaultValue = 100000)]
public double takeProfit { get; set; }
[Parameter(DefaultValue = 100000)]
public double stopLoss { get; set; }
[Parameter(DefaultValue = 60)]
public int fastPeriod { get; set; }
[Parameter(DefaultValue = 240)]
public int slowPeriod { get; set; }
[Parameter(DefaultValue = 0.01)]
public double lots { get; set; }
[Parameter(DefaultValue = 1)]
public int maxOrder { get; set; }
private ExponentialMovingAverage emaFast;
private ExponentialMovingAverage emaSlow;
protected override void OnBar()
{
// Put your core logic here
emaFast = Indicators.ExponentialMovingAverage(Source, fastPeriod);
emaSlow = Indicators.ExponentialMovingAverage(Source, slowPeriod);
int currentBar = Bars.Count - 1;
var positions = Positions.FindAll("Order");
if (emaFast.Result.LastValue > emaSlow.Result.LastValue)
{
Close(TradeType.Sell);
Open(TradeType.Buy, lots);
}
if (emaFast.Result.LastValue < emaSlow.Result.LastValue)
{
Close(TradeType.Buy);
Open(TradeType.Sell, lots);
}
}
private void Close(TradeType tradeType)
{
foreach (var position in Positions.FindAll("Order", SymbolName, tradeType))
ClosePosition(position);
}
private void Open(TradeType tradeType, double lots)
{
var position = Positions.FindAll("Order", SymbolName, tradeType);
var volumeInUnits = Symbol.QuantityToVolumeInUnits(lots);
if (position == null || position.Length < maxOrder)
ExecuteMarketOrder(tradeType, SymbolName, (double)volumeInUnits, "Order", stopLoss, takeProfit);
}
}
}
Ciao, la strategia Dynamic Range Revert Money Management è una miglioria alla strategia Dynamic Range Revert! (Pazzesco vero?! 😀 ) Si tratta della stessa strategia dove però i lotti cambiano in percentuale.
Ciao sono Drilon e sono un programmatore con la passione per la finanza personale. In questa strategia si imposta quanto del nostro capitale si vuole rischiare ad ogni trade, ad esempio l’1%! La logica che c’è sotto poi è la stessa che trovi qui (no dovevi cliccare QUI, c’è il link, non in questo, dai te lo rimetto qui, stasera mi è presa così…non sono simpatico scusa)
Risultati
Andiamo al sodo e vediamo il risultato!
dynamic range revert money management – risultati
Questo grafico è l’equityline, ovvero l’andamento. Partendo da 450$ si arriva a circa 3400$.
Aspetta non è così semplice, questa vale solo per EURCAD a timeframe 1 minuto!
Niente male lo so, ma non farti ingannare dai, ovviamente questo è un backtest, in live i risultati non saranno così, per via dello spread e le commissioni che qui è sono statiche (non zero, non mi ricordo che valore di preciso).
Ok abbiamo visto il grafico, vediamo più nel dettaglio però.
Un dato molto importante per me è sempre il Drawdown poiché devo essere in grado di sostenerlo sia economicamente che mentalmente (terribile veder scendere il valore dei soldi). In questo caso si tratta di circa un 12% di drawdown.
Non è tantissimo, però non è nemmeno poco, anche se per un guadagno del genere ne potrebbe valere la pena!
Vediamo che ha aperto circa 3000 ordini, quindi i dati sono abbastanza affidabile. Se un backtest di una strategia si fa su 10 ordini i dati che ottieni puoi evidenziarli, sottolinearli, accartocciare il foglio e buttare tutto! NON SONO ABBASTANZA! NON è ATTENDIBILE!
Un altro valore importante sono gli ordini consecutivi che sono andati in stopLoss, anche questo principalmente per una questione mentale (il rischio rendimento vedrai che non è come ti aspetti).
Personalmente, preferisco fare piccoli profitti costanti e prendere una batosta raramente, rispetto a prendere tanti stopLoss e un grande takeProfit. Mentalmente mi ammazza e mi porterebbe a fare cazzate!
Vabbè basta, io il mio l’ho detto, tieni il codice!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
[Robot(AccessRights = AccessRights.None)]
public class IIDynamicRangeBreakoutREVERTMM : Robot
{
[Parameter(DefaultValue = 10)]
public double takeProfit { get; set; }
[Parameter(DefaultValue = 10)]
public double stopLoss { get; set; }
[Parameter(DefaultValue = 8)]
public int hourEnter { get; set; }
[Parameter(DefaultValue = 18)]
public int hourExit { get; set; }
[Parameter(DefaultValue = 8)]
public int hourClosingOpen{ get; set; }
[Parameter(DefaultValue = 18)]
public int hourClosingExit { get; set; }
[Parameter(DefaultValue = 1)]
public int maxOrder { get; set; }
[Parameter(DefaultValue = 0)]
public double maxRange { get; set; }
[Parameter(DefaultValue = 999999)]
public double minRange { get; set; }
[Parameter(DefaultValue = 0.01)]
public double lots { get; set; }
[Parameter(DefaultValue = 3)]
public int stopLossRiskPercent { get; set; }
protected override void OnStart()
{
Positions.Closed += OnPositionsClosed;
}
protected override void OnTick()
{
// Handle price updates here
if(!checkTime()){
// Break Range
if(Bars.LastBar.Close > maxRange && maxRange != 0){
// Open BUY
lots = DisplayPositionSizeRiskOnChart();
if(lots >= 0.00){
Open(TradeType.Sell, lots);
maxRange = 0;
minRange = 999999;
}
}
if(Bars.LastBar.Close < minRange && minRange != 999999){
// Open SELL
lots = DisplayPositionSizeRiskOnChart();
if(lots >= 0.00){
Open(TradeType.Buy, lots);
maxRange = 0;
minRange = 999999;
}
}
}
/*if(checkClosingTime()){
CloseAll();
}*/
}
protected override void OnBar()
{
if(checkTime()){
// Set Range
if(Bars.LastBar.High > maxRange ){
maxRange = Bars.LastBar.High;
}
if(Bars.LastBar.Low < minRange ){
minRange = Bars.LastBar.Low;
}
}
}
protected override void OnStop()
{
CloseAll();
}
private bool checkTime()
{
DateTime date = Server.Time;
if (date.Hour >= hourEnter && date.Hour <= hourExit && hourEnter <= hourExit)
{
return true;
}
else
{
return false;
}
}
private bool checkClosingTime()
{
DateTime date = Server.Time;
if (date.Hour >= hourClosingOpen && date.Hour <= hourClosingExit && hourClosingOpen <= hourClosingExit)
{
return true;
}
else
{
return false;
}
}
private void CloseAll()
{
foreach (var position in Positions.FindAll("DynamicRangeBreakoutREVERT", SymbolName))
{
ClosePosition(position);
}
}
private void Close(TradeType tradeType)
{
foreach (var position in Positions.FindAll("DynamicRangeBreakoutREVERT", SymbolName, tradeType))
ClosePosition(position);
}
private void Open(TradeType tradeType, double lots)
{
var position = Positions.FindAll("DynamicRangeBreakoutREVERT", SymbolName, tradeType);
var volumeInUnits = Symbol.QuantityToVolumeInUnits(lots);
if (position == null || position.Length < maxOrder)
ExecuteMarketOrder(tradeType, SymbolName, volumeInUnits, "DynamicRangeBreakoutREVERT", stopLoss, takeProfit);
}
private void OnPositionsClosed(PositionClosedEventArgs args)
{
Print("Closed positions");
var position = args.Position;
/* if (position.NetProfit > 0)
{
lots = 0.03;
}
else
{
lots *= 2;
}*/
}
private double DisplayPositionSizeRiskOnChart()
{
double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;
double positionSizeForRisk = (Account.Balance * stopLossRiskPercent / 100) / (stopLoss * costPerPip);
Print(Account.Balance, " ",positionSizeForRisk, " ",(stopLoss * costPerPip));
string text = stopLossRiskPercent + "% x " + stopLoss + "pip = " + Math.Round(positionSizeForRisk, 2) + " lot";
ChartObjects.DrawText("positionRisk", text, StaticPosition.TopRight, Colors.Yellow);
return Math.Round(positionSizeForRisk, 2);
}
}
}
questi sono i parametri che devi impostare:
takeProfit: 15
stopLoss: 40
hourEnter: 18
hourExit: 19
hourClosingEnter: 18
hourClosingExit: 23
maxOrder: 1
minRange: 99999
lots: 0.01
stopLossRisk: 1
Mi raccomando, la strategia può funzionare anche con altre valute, ma con questi parametri specifici funziona sono in EURCAD a 1 minuto!
Da qui puoi vedere come utilizzare cTrader (piattaforma che utilizzo): LINK