Page 1 of 1

Get multiple Boolean Signal values from an External Indicator

Posted: Tue Jan 19, 2021 10:45 pm
by kmarryat
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

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)