Get multiple Boolean Signal values from an External Indicator
Posted: Tue Jan 19, 2021 10:45 pm
Hello All,
This is more of a test script than a full script but I thought it might be useful for anyone playing around with getting values from External Indicators.
I apologize in advance for all the code comments. More than half the script is comments. I have a habit of creating something, then coming back to it later and not understanding what I did. So I comment heavily to ensure anyone that wants to use/edit/improve on it knows what's happening in the script.
By default, TradingView only allows you to get one plot value from an external indicator. I’ve been working on a backtesting strategy script that uses Filters and Signals from a separate study script. This allows me to only include the trade management code in the strategy script, and run all the Strategy rules, triggers, and filters from another script. I got the idea from the great work that PineCoders did on their Backtesting Trading Engine: https://www.tradingview.com/script/dYqL ... ineCoders/
The script can pass up to 9 separate Boolean signal values from a Sender script to a Receiver script. Each signal is represented independently so multiple signals can be combined and sent on the same bar.
The Sender portion of the script converts the 9 Boolean signal values into a single decimal value, that is passed to the Receiver using a plot and external Indicator Input. Then the Receiving Script accesses the Externally plotted Signal value and converts it back to a series of Booleans/Binary Values (1's and 0's).
Hope someone finds it useful. Enjoy!
Ken
This is more of a test script than a full script but I thought it might be useful for anyone playing around with getting values from External Indicators.
I apologize in advance for all the code comments. More than half the script is comments. I have a habit of creating something, then coming back to it later and not understanding what I did. So I comment heavily to ensure anyone that wants to use/edit/improve on it knows what's happening in the script.
By default, TradingView only allows you to get one plot value from an external indicator. I’ve been working on a backtesting strategy script that uses Filters and Signals from a separate study script. This allows me to only include the trade management code in the strategy script, and run all the Strategy rules, triggers, and filters from another script. I got the idea from the great work that PineCoders did on their Backtesting Trading Engine: https://www.tradingview.com/script/dYqL ... ineCoders/
The script can pass up to 9 separate Boolean signal values from a Sender script to a Receiver script. Each signal is represented independently so multiple signals can be combined and sent on the same bar.
The Sender portion of the script converts the 9 Boolean signal values into a single decimal value, that is passed to the Receiver using a plot and external Indicator Input. Then the Receiving Script accesses the Externally plotted Signal value and converts it back to a series of Booleans/Binary Values (1's and 0's).
Hope someone finds it useful. Enjoy!
Ken
Code: Select all
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © kmarryat
// This script was created to pass up to 9 separate Boolean signal values from a Sender script to a Receiver script
// It uses 2 custom functions
// f_ConvertBD does Boolean/Binary to Decimal conversion
// f_ConvertDB does Decimal to Binary/Boolean conversion
// The Sender portion of the script converts the Boolean signal values into a single decimal value
// that can be passed to the Receiver using a plot and external Indicator Input
// The Sending Script plots the combined signals as a single Decimal Value
// The Receiving Script accesses the Externally plotted Signal value and converts it back to a series of Binary Values (1's and 0's)
// The individual Binary values are then assigned to 9 separate receiver Signal Variables as either a 1 or 0 value
// For Testing Validation the variables are converted to strings and combined so they can be printed on the chart using a label
// Script can be run by itself for testing:
// Add Indicator to Chart
// Change Input Values to see Signal Values plotted on Chart update
// Script can be broken into 2 Parts for Testing of the Sender and Receiver portions:
// Copy 2 Sections to 2 separate study scripts
// Uncomment the 3 lines of the 2nd script identified in the RECEIVER SECTION
// Save both studies then add Sender & Receiver studies to chart
//
// In the Receiver Settings:
// Change the Signal Source to "External"
// Change External Indicator Signal to "Sender"
//
// In the Sender Settings:
// Change Input Values to see the Signal Values on the Receiver chart update
// Top to Bottom Input Values are represented Right to Left
// Checked/true is 1, Unchecked/false is 0
// NOTE: If you get the following error when saving or adding the Receiver study:
//
// <<<< Script could not be translated from: ["Internal","External"] >>>>
//
// You forgot to uncomment the 3 required lines at the beginning of the receiver section
//<<<<<SENDER_SECTION>>>>>
//@version=4
study(title="Decimal-Binary Signal Conversion - Sender", shorttitle="Sender")
//Testing Inputs to Generate Signal Values
//Replace with Actual Signal Value Calculations in your final Sender Script
Signal1 = input(defval=false, title="Setup (1)", type=input.bool)
Signal2 = input(defval=false, title="Validation (2)", type=input.bool)
Signal3 = input(defval=false, title="Entry (4)", type=input.bool)
Signal4 = input(defval=false, title="Exit (8)", type=input.bool)
Signal5 = input(defval=false, title="Signal5 (16)", type=input.bool)
Signal6 = input(defval=false, title="Signal6 (32)", type=input.bool)
Signal7 = input(defval=false, title="Signal7 (64)", type=input.bool)
Signal8 = input(defval=false, title="Signal8 (128)", type=input.bool)
Signal9 = input(defval=false, title="Signal9 (256)", type=input.bool)
//Function to convert multiple Boolean/binary Signal Values to a single Decimal Signal Value
//Each If statement should be followed by a Boolean value representing a Signal test result
//Convert Binary to Decimal
f_ConvertBD() =>
_Signal=0
if Signal1
_Signal := _Signal + 1 //If Signal1 is true add 1 to _Signal value
if Signal2
_Signal := _Signal + 2 //If Signal2 is true add 2 to _Signal value
if Signal3
_Signal := _Signal + 4 //If Signal3 is true add 4 to _Signal value
if Signal4
_Signal := _Signal + 8 //If Signal4 is true add 8 to _Signal value
if Signal5
_Signal := _Signal + 16 //If Signal5 is true add 16 to _Signal value
if Signal6
_Signal := _Signal + 32 //If Signal6 is true add 32 to _Signal value
if Signal7
_Signal := _Signal + 64 //If Signal7 is true add 64 to _Signal value
if Signal8
_Signal := _Signal + 128 //If Signal8 is true add 128 to _Signal value
if Signal9
_Signal := _Signal + 256 //If Signal9 is true add 256 to _Signal value
_Signal //Return the final Signal Value
//Store the converted Signal Value in a Variable
Signal = f_ConvertBD()
//Plot Signal Value for use as External Filter by Receiver study
plot(Signal,"Signal",color.yellow)
//<<<<<<<<< Code Above for Sender Script * * * * * Code Below for Receiver Script>>>>>>>>>>>
//<<<<<RECEIVER_SECTION>>>>>
//Uncomment Next 3 Lines if copying to separate Receiver Script
////@version=4
//study(title="Decimal-Binary Signal Conversion - Receiver", shorttitle="Receiver")
//Signal = 0
// <<<<< Inputs to Select Signal from Sender Script >>>>>
// Not Needed for testing. Only required when breaking Script into Sender & Receiver Scripts
// Will only work if there are no other input.source type inputs in the Receiver Script
SignalSource = input(defval="Internal", title="Signal Source", type=input.string, options=["Internal","External"])
ExternalSignal = input(defval=close, title="External Indicator Signal", type=input.source)
//Function to Convert single Decimal Signal value back to multiple Binary Signal Values (multiple 0's and 1's)
//Convert Decimal to Binary
f_ConvertDB(_Input) =>
_1v = floor(_Input / 2), _1r = floor(_Input % 2) //Calculate 1st Value (Input/2) , and 1st Remainder (Remainder of Input/2)
_2v = floor(_1v / 2), _2r = floor(_1v % 2) //Calculate 2nd Value (1st Value/2) , and 2nd Remainder (Remainder of 1st Value/2)
_4v = floor(_2v / 2), _4r = floor(_2v % 2) //Calculate 3rd Value (2nd Value/2) , and 3rd Remainder (Remainder of 2nd Value/2)
_8v = floor(_4v / 2), _8r = floor(_4v % 2) //Calculate 4th Value (3rd Value/2) , and 4th Remainder (Remainder of 3rd Value/2)
_16v = floor(_8v / 2), _16r = floor(_8v % 2) //Calculate 5th Value (4th Value/2) , and 5th Remainder (Remainder of 4th Value/2)
_32v = floor(_16v / 2), _32r = floor(_16v % 2) //Calculate 6th Value (5th Value/2) , and 6th Remainder (Remainder of 5th Value/2)
_64v = floor(_32v / 2), _64r = floor(_32v % 2) //Calculate 7th Value (6th Value/2) , and 7th Remainder (Remainder of 6th Value/2)
_128v = floor(_64v / 2), _128r = floor(_64v % 2) //Calculate 8th Value (7th Value/2) , and 8th Remainder (Remainder of 7th Value/2)
_256v = floor(_128v / 2), _256r = floor(_128v % 2) //Calculate 9th Value (8th Value/2) , and 9th Remainder (Remainder of 8th Value/2)
[_256r,_128r,_64r,_32r,_16r,_8r,_4r,_2r,_1r] //Return all 9 Remainder Values (Each will be 0 or 1)
//Set SelectedSignal to whichever Signal is Selected in the SignalSource Input
SelectedSignal = SignalSource == "Internal" ? Signal : ExternalSignal
//Convert the SelectedSignal from Decimal to Binary and Assign the 9 individual signal values to Variables
[Signal_9,Signal_8,Signal_7,Signal_6,Signal_5,Signal_4,Signal_3, Signal_2,Signal_1] = f_ConvertDB(SelectedSignal)
///Print Selected Signal Value and its Converted Binary Value to the Chart
//Convert Signal Values to Text and Combine into 1 Text String
Result = SignalSource + " Signal : " + tostring(SelectedSignal) + "\nBinary Version : " + tostring(Signal_9) + tostring(Signal_8) + tostring(Signal_7) + tostring(Signal_6) + tostring(Signal_5) + tostring(Signal_4) + tostring(Signal_3) + tostring(Signal_2) + tostring(Signal_1)
//Print Converted Signal Values on Chart using a Label
var _lbl=label.new(x=time,y=0,text=Result,xloc=xloc.bar_time,yloc=yloc.price,color=#00000000,style=label.style_none,textcolor=color.yellow,size=size.large,textalign=text.align_left)
label.set_xy(_lbl, time, 0)
label.set_text(_lbl, Result)