Entry, Target, Profit Loss (PnL) Watchlists, Labels of Owned Equities In ThinkOrSwim

I have Pos. Qty, Avg Price, and P/L Open on my Current Account Positions watchlist which is a default watchlist... I also used P/L Day before I switched to day trading only...
 
I am trying to code what I'm calling a "Profit Risk Factor". You can think of it similar to a trailing stop, but I want is a label as a percentage. Hoping someone can help me code it, if it is possible.

Profit Risk Factor
Def: How much of the profit that I would have ultimately made am I losing?
i.e., I’m willing to lose some of my profit, but not all of it.
i.e., I’m good with a Profit Risk Factor <= 40%

  • I get into a position
  • As profits go up, capture the highest value (A)
  • B = current profit
  • (A-B)/A = profit risk (as a percentage)
  • If highest profit is negative (A) [i.e., a loss and it never turns positive]
    • ABS((A-B)/A) = profit risk (as a percentage)
 
@epete Try this - make sure you test it thoroughly. I have no idea if this will output the results you desire. I'd appreciate feedback after you test it, and I plan to test the label next week on my end as well.

If anyone knows a simpler way to code this or finds a mathematical error, I'm all ears to learn.

Ruby:
# Profit Drawdown
# Pensar
# 08.06.2021

def entry = if IsNaN(GetAveragePrice()) then entry[1] else GetAveragePrice();
def newprofithighs = if entry > 0 then if high > high[1] then high else newprofithighs[1] else double.nan;
def maxprofit = HighestAll(newprofithighs);
def distancefromentry = entry - maxprofit;
def drawdown = (maxprofit - close)/distancefromentry;
addlabel(if entry > 0 then 1 else 0, aspercent(drawdown),color.red);

# end code
 
Amazing! Thank you SO much. I will test it out next week. Can't wait... :)
Just don't get your hopes up too high :D

By the way, it will only show up when you are in a trade, otherwise it will disappear.
 
Last edited:
Thanks Pensar. Something didn't work quite right. I got a bunch of "NaN" displays. At times I got negative values for PRF (profit risk factor) even though the profit was going up and not coming down. I'll have to look more into the code tomorrow.
 
Thanks Pensar. Something didn't work quite right. I got a bunch of "NaN" displays. At times I got negative values for PRF (profit risk factor) even though the profit was going up and not coming down. I'll have to look more into the code tomorrow.
@epete I've been having issues also with some stocks. I'll look into it as well.
 
@Pensar try this one
Code:
# Profit Risk Factor
# epete
# 08.10.2021

def entry = if IsNaN(GetAveragePrice()) then entry[1] else GetAveragePrice();
def newprofithighs = if entry > 0 then (if high > high[1] then high else newprofithighs[1]) else double.nan;
def maxprofit = HighestAll(newprofithighs);
def distancefromentry = maxprofit - entry;
def PRF = if newprofithighs<entry then AbsValue(((newprofithighs-entry)/newprofithighs)-1) else (maxprofit-newprofithighs)/(maxprofit-entry);
AddLabel(yes, "PRF: " + AsPercent(PRF),color.LIGHT_ORANGE);
 
This one accounts for long or short trades
Code:
# Profit Risk Factor
# epete
# 08.10.2021

def entry = if IsNaN(GetAveragePrice()) then entry[1] else GetAveragePrice();
def newprofithighs = if entry > 0 then (if high > high[1] then high else newprofithighs[1]) else double.nan;
def maxprofit = HighestAll(newprofithighs);
def distancefromentry = maxprofit - entry;
def PRF = if qty>0 then
(if newprofithighs<entry then AbsValue(((newprofithighs-entry)/newprofithighs)-1) else (maxprofit-newprofithighs)/(maxprofit-entry)) else
(if newprofithighs>entry then AbsValue(((entry-newprofithighs)/entry)-1) else (newprofithighs-maxprofit)/(entry-maxprofit));
AddLabel(qty<>0, "PRF: " + AsPercent(PRF),color.LIGHT_ORANGE);
 
@Pensar try this one
Code:
# Profit Risk Factor
# epete
# 08.10.2021

def entry = if IsNaN(GetAveragePrice()) then entry[1] else GetAveragePrice();
def newprofithighs = if entry > 0 then (if high > high[1] then high else newprofithighs[1]) else double.nan;
def maxprofit = HighestAll(newprofithighs);
def distancefromentry = maxprofit - entry;
def PRF = if newprofithighs<entry then AbsValue(((newprofithighs-entry)/newprofithighs)-1) else (maxprofit-newprofithighs)/(maxprofit-entry);
AddLabel(yes, "PRF: " + AsPercent(PRF),color.LIGHT_ORANGE);
@epete did this code fix the problems?
 
Mine worked, but yours didn't. I also had to replace "double.nan" with "high" to not get the NaN on the label. Since I want to show this label only when I'm in a position; do I have to "reset" the values (e.g., newprofithighs) for the 2nd time I'm in a trade? Say I buy one set of shares, watch the PRF change; then sell the stock; then buy shares again. Will the "def" values need to be reset? i.e., "if qty=0 then reset variable values..."

Now I'm going to attempt to create an "accelerating trailing stop". I'm willing to take a larger loss (of profits) in the early stages of the stock run-up (so if my stock goes from $10 to $20 I'm willing to take as much as a 100% loss of that profit ($10) - which would equate to a washout; but as profits get larger, I'm not as willing to give as much of the profit back. I want the accelerated trailing stop to get tighter and tighter as the profits go up. My PRF then could continue to go from 100% down to say 40% (if that were my MPF "minimum profit factor") but never would I give back anything more than a defined MPF. Does that make sense?
 
Last edited:
Mine worked, but yours didn't. I also had to replace "double.nan" with "high" to not get the NaN on the label. Since I want to show this label only when I'm in a position; do I have to "reset" the values (e.g., newprofithighs) for the 2nd time I'm in a trade? Say I buy one set of shares, watch the PRF change; then sell the stock; then buy shares again. Will the "def" values need to be reset? i.e., "if qty=0 then reset variable values..."
I would think that when you close out the trade that since the quantity == 0 at that point, nothing needs to be done.
Now I'm going to attempt to create an "accelerating trailing stop". I'm willing to take a larger loss (of profits) in the early stages of the stock run-up (so if my stock goes from $10 to $20 I'm willing to take as much as a 100% loss of that profit ($10) - which would equate to a washout; but as profits get larger, I'm not as willing to give as much of the profit back. I want the accelerated trailing stop to get tighter and tighter as the profits go up. My PRF then could continue to go from 100% down to say 40% (if that were my MPF "minimum profit factor") but never would I give back anything more than a defined MPF. Does that make sense?
Try looking at a volatility trailing stop or the Parabolic SAR, they are similar to what you want. Coding this might be complicated.
 
Mine worked, but yours didn't. I also had to replace "double.nan" with "high" to not get the NaN on the label. Since I want to show this label only when I'm in a position; do I have to "reset" the values (e.g., newprofithighs) for the 2nd time I'm in a trade? Say I buy one set of shares, watch the PRF change; then sell the stock; then buy shares again. Will the "def" values need to be reset? i.e., "if qty=0 then reset variable values..."

Now I'm going to attempt to create an "accelerating trailing stop". I'm willing to take a larger loss (of profits) in the early stages of the stock run-up (so if my stock goes from $10 to $20 I'm willing to take as much as a 100% loss of that profit ($10) - which would equate to a washout; but as profits get larger, I'm not as willing to give as much of the profit back. I want the accelerated trailing stop to get tighter and tighter as the profits go up. My PRF then could continue to go from 100% down to say 40% (if that were my MPF "minimum profit factor") but never would I give back anything more than a defined MPF. Does that make sense?
i'm experimenting with making a version of this.
 
I'm trying to save the maximum high value of a stock/option during a trade. What I get with the following code is always the overall highest value - not the highest value within the trade. Let's say my entry price is 2.6; the newhigh is 2.72; and what I'd like to capture is the highest value SINCE my entry.

It doesn't seem to matter whether I use the first "def maxhigh" or the second "def maxhigh" (commented out). They both produce the overall high value of 17.76. But I don't want that value. I want the highest value since I bought into the stock/option.

Code:
def entry   = if IsNaN(GetAveragePrice()) then entry[1] else GetAveragePrice();
def newhigh = if entry>0 then (if high > high[1] then high else newhigh[1]) else high;
def maxhigh = HighestAll(newhigh);
#def maxhigh = if IsNaN(maxhigh[1]) then newhigh else if newhigh > maxhigh[1] then newhigh else maxhigh[1];

AddLabel(yes, "entry: " + entry + " newhigh: " + newhigh + " maxhigh: " + maxhigh,  color.LIGHT_GRAY);
2021-08-17-11-18-39.png
 
Last edited:
I'm trying to save the maximum high value of a stock/option during a trade. What I get with the following code is always the overall highest value - not the highest value within the trade. Let's say my entry price is 2.6; the newhigh is 2.72; and what I'd like to capture is the highest value SINCE my entry.

It doesn't seem to matter whether I use the first "def maxhigh" or the second "def maxhigh" (commented out). They both produce the overall high value of 17.76. But I don't want that value. I want the highest value since I bought into the stock/option.

Code:
def entry   = if IsNaN(GetAveragePrice()) then entry[1] else GetAveragePrice();
def newhigh = if entry>0 then (if high > high[1] then high else newhigh[1]) else high;
def maxhigh = HighestAll(newhigh);
#def maxhigh = if IsNaN(maxhigh[1]) then newhigh else if newhigh > maxhigh[1] then newhigh else maxhigh[1];

AddLabel(yes, "entry: " + entry + " newhigh: " + newhigh + " maxhigh: " + maxhigh,  color.LIGHT_GRAY);

I made it a lower study and added a plot so you can visualize what this is finding. Just remove those when you're satisfied with the results.

Also, this finds the high of the entry candle though it's possible you weren't in the trade yet. If you entered at the bottom of a big red candle then your trade never touched that high. Depending on how you intend to use this some cases could be a little misleading.

Ruby:
declare lower;

def maxhigh =
  if GetQuantity() != 0 then
    if GetQuantity()[1] == 0 then high
    else Max(high, maxhigh[1])
  else maxhigh[1]
;

plot test = maxhigh;
AddLabel(yes, maxhigh, Color.LIGHT_GRAY);
 
i haven't used getaverageprice() , so this is theoretical
maybe using getquantity is a better variable to use, instead of GetAveragePrice() , as slippage used in his code.

your second line ends with high, so it always sends a high on to highestall().
if there are no quantities, then you don't want a high, so set it to a low number.
try changing the last parameter , from high to 0.
def newhigh = if entry>0 then (if high > high[1] then high else newhigh[1]) else 0;

this line isn't quite right, if you want the price to exist only during a trade.
def entry = if IsNaN(GetAveragePrice()) then entry[1] else GetAveragePrice();
once a trade occurs, it retains a price, even after the trade is closed.
change it to something like this.
...... if a valid quantity then high else 0 ....

if you have several trades, your (fixed) code could find the highest of all the trades.
if you want to find the highest of each trade, then you will have to add some kind of trade counter and add it in the formulas.


********************
EDIT:::
this may have to be changed. i was assuming values of 0 or 1+ . if getquantity can be a negative number, then different checks in the following formula will be needed.

new*********
this looks for a change from 0 to some quantity
def tradecounter = if ( GetQuantity()[1] == 0 and GetQuantity() <> 0 ) then tradecounter[1] + 1 else tradecounter[1];


original**********
( may have to add isnan() to check for errors..?)
this looks for a transition of getquantity, from a low to a high
def tradecounter = if ( !GetQuantity()[1] and GetQuantity() ) then tradecounter[1] + 1 else tradecounter[1];

****************

def hi1 = highestall( if tradecounter == 1 then highestall(newhigh) else 0 );
def hi2 = highestall( if tradecounter == 2 then highestall(newhigh) else 0 );
....
 
Last edited:
i haven't used getaverageprice() , so this is theoretical
maybe using getquantity is a better variable to use, instead of GetAveragePrice() , as slippage used in his code.

I don't think there's really an advantage either way in this case. I just usually default to getting the quantity first because it tells me if the position is long or short. And the function name has fewer letters making for slightly shorter lines of code.
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
392 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top