Trailing Stop Extension Sample

<pss_extension min_pss_version="7.1" name="Trailing Stop Alert" version="1.0.16">Trailing Stop Alert
<author email="support@dtlink.com" name="DTLink Software" url="http://www.dtlink.com" />
<script language="VBScript">
<![CDATA[

' Trailing Stop extension for Personal Stock Streamer
' Copyright © 2004-2005 by DTLink Software, All rights reserved.
' http://www.dtlink.com
' written by Anatoly Ivasyuk

' ================================================

class TrailingStopHandler

	' menu event handler
	public Function OnMenuItemSelected ( id )
		'Application.DebugTrace "TrailingStopHandler::OnMenuItemSelected(" + CStr(id) + ")"

		' set trailing stop for selected tickers
		If (id = menuIdSetStop) Then
			'Application.DebugTrace "TrailingStopHandler::OnMenuItemSelected()  selected menuIdSetStop"
			Set selectedTickers = Application.ActiveDocument.Selection.Tickers
			
			If (selectedTickers.Count > 0) Then
				Set wndManager = Application.GetObject("WindowManager")
				Set wndBrowser = wndManager.CreateBrowserWindow(300, 140, me)
			
				' get the default stop percentage from the first ticker
				Value = 0
				On Error Resume Next
				Value = selectedTickers.Item(0).GetProperty("_TrailingStopPct")
				On Error Goto 0
				If Value = 0 Then
					Value = 20
				End If
				
				' create the HTML form for the dialog
				form = "<body bgcolor=white><form name=form1 method=post target=" + Chr(34) + "x" + Chr(34) + ">"
				form = form + "<table cellspacing=0 cellpadding=2><tr><td align=middle>Stop Percentage:</td><td align=middle><input type=text size=4 name=pct value=" + CStr(Value) + "></td></tr>"
				form = form + "<tr><td align=middle>Alert Action:</td><td align=middle><select name=act>"
				
				Set alertManager = Application.GetObject("AlertManager")
				first = true
				For Each action in alertManager.Actions
					if first then
						form = form + "<option selected>"
						first = false
					else
						form = form + "<option>"
					end if
					form = form + action.GetProperty("Name") + "</option>"
				Next
				form = form + "</select></td></tr></table>"
				form = form + "<p align=center><input type=submit value=" + Chr(34) + "OK" + Chr(34) + ">&nbsp;&nbsp;<input type=submit value=" + Chr(34) + "Cancel" + Chr(34) + ">"
				form = form + "</form></body>"
				
				wndBrowser.SetHTML(form)
				wndBrowser.Title = "Set Trailing Stop"
			Else
				MsgBox "No tickers have been selected.", vbOKOnly, "Trailing Stop"
			End If

			' set return value to indicate that menu selection was processed
			OnMenuItemSelected = True
		
		' cancel trailing stop for selected tickers
		ElseIf (id = menuIdCancelStop) Then
			'Application.DebugTrace "TrailingStopHandler::OnMenuItemSelectd() selected menuIdCancelStop"
			
			For Each ticker in Application.ActiveDocument.Selection.Tickers
				ticker.SetProperty "_TrailingStopMark", 0
				ticker.SetProperty "_TrailingStopPct", 0
				ticker.SetProperty "_TrailingStopComment", ""

				Set ViewManager = Application.GetObject("ViewManager")
				ViewManager.UpdateObjectInView(ticker)
			Next
		End If
	end Function

	' form submission handler
	public Function OnFormSubmitted ( form )
		'Application.DebugTrace "TrailingStopHandler::OnFormSubmitted()  pct=" + form.Value("pct") + " act=" + form.Value("act")
		
		If (form.Value("submit") = "OK") Then
			SetMarks form.Value("pct"), form.Value("act")
		End If
		
		' release the form window
		Set wndBrowser = Nothing
		
		OnFormSubmitted = true
	end Function

	' ticker update handler
	public Function OnTickerUpdated ( ticker )
		' get the trailing stop value
		dStopMark = 0
		dStopPct = 0
		
		On Error Resume Next
		dStopMark = CDbl(ticker.GetProperty("_TrailingStopMark"))
		dStopPct = CDbl(ticker.GetProperty("_TrailingStopPct"))
		On Error Goto 0
		
		' if the trailing stop is set for this ticker...
		If (dStopMark > 0 And dStopPct > 0) Then
			
			' check if we need to increase the trailing stop mark
			dPrice = ticker.GetProperty("Price")
			
			If (dPrice > dStopMark) Then
				dStopMark = dPrice

				'Application.DebugTrace "TrailingStopHandler::OnTickerUpdated()  new dStopMark=" + FormatNumber(dStopMark, 2)

				ticker.SetProperty "_TrailingStopMark", dStopMark

				' update the UI
				tmp = FormatNumber(CDbl(dStopMark), 2) + ", " + FormatNumber(CDbl(dStopPct), 2) + "%"
				ticker.SetProperty "_TrailingStopComment", tmp

				Set ViewManager = Application.GetObject("ViewManager")
				ViewManager.UpdateObjectInView(ticker)
			
			' otherwise check to see if we've gone over the threshold
			Else
				dDiffPct = ((dStopMark - dPrice) / dStopMark) * 100
				
				'Application.DebugTrace "TrailingStopHandler::OnTickerUpdated()  dStopMark=" + FormatNumber(dStopMark, 2) + " dPrice=" + FormatNumber(dPrice,2) + " dDiffPct=" + FormatNumber(dDiffPct,2)

				' check if we need to execute the alert action
				If (dDiffPct >= dStopPct) Then
					'Application.DebugTrace "TrailingStopHandler::OnTickerUpdated()  ALERT!!!"
					
					RunAlertAction ticker.GetProperty("_TrailingStopAlertAction"), ticker
				End If
			End If
		End If
	end Function
	
	' find the starting high water mark for the given ticker
	public Function GetDefaultStopMark ( ticker )
		dMark = ticker.GetProperty("Avg. Basis")
		
		' if there are no current holdings or the current price is higher, then set the high water mark from the current price
		dTickerPrice = ticker.GetProperty("Price")
		
		If (dMark = 0 Or dTickerPrice > dMark) Then
			dMark = dTickerPrice
		End If
		
		GetDefaultStopMark = dMark
	end Function
	
	' set the trailing stop mark
	public Function SetMarks( dStopPct, szActionName )
		For Each ticker in Application.ActiveDocument.Selection.Tickers
			dStopMark = GetDefaultStopMark(ticker)
			
			If (dStopMark > 0) Then
				'Application.DebugTrace "TrailingStopHandler::OnMenuItemSelected()  set stop for " + ticker.GetProperty("Symbol") + " at " + FormatNumber(CDbl(dStopMark), 2)
			
				ticker.SetProperty "_TrailingStopMark", dStopMark
				ticker.SetProperty "_TrailingStopPct", dStopPct
				ticker.SetProperty "_TrailingStopAlertAction", szActionName

				' update the UI
				tmp = FormatNumber(CDbl(dStopMark), 2) + ", " + FormatNumber(CDbl(dStopPct), 2) + "%"
				ticker.SetProperty "_TrailingStopComment", tmp
				
				Set ViewManager = Application.GetObject("ViewManager")
				ViewManager.UpdateObjectInView(ticker)
			Else
				nValue = MsgBox("Unable to set trailing stop for " + ticker.GetProperty("Symbol"), vbOKCancel, "Trailing Stop")
				
				If nValue = vbCancel Then
					Exit For
				End If
			End If
		Next
	end Function

	' run the specified alert action on the given ticker
	public Function RunAlertAction ( name, ticker )
		'Application.DebugTrace "TrailingStopHandler::RunAlertAction()  name=" + name

		Set manager = Application.GetObject("AlertManager")
		
		If Not manager Is Nothing Then
			For Each action in manager.Actions
				If action.GetProperty("Name") = name Then
					action.Run2 ticker, "Trailing Stop"
					Exit For
				End If
			Next
		End If
		
	end Function
	
	' our menu items
	Dim menuIdSetStop, menuIdCancelStop
	Dim wndBrowser

end Class

' ================================================
' initialization

Set EventManager = Application.GetObject("EventManager")
Set MenuManager = Application.GetObject("MenuManager")
Set ViewManager = Application.GetObject("ViewManager")

Set Handler = new TrailingStopHandler

' create the custom menu commands
If Not MenuManager Is Nothing Then
	Set MainMenu = MenuManager.MainMenu
	nToolMenu = MainMenu.Find("Tools")

	' create the Tools top-level menu if it doesn't exist
	If (nToolMenu = -1) Then
		nHelpMenu = MainMenu.Find("Help")

		Set ToolMenu = MainMenu.InsertMenu(nHelpMenu, "Tools")
	Else
		Set ToolMenu = MainMenu.GetSubMenu(nToolMenu)
	End If

	' actually create the menu commands and save the ids for later
	If Not ToolMenu Is Nothing Then
		ToolMenu.InsertSeparator ToolMenu.ItemCount
		Handler.menuIdSetStop = ToolMenu.InsertItem(ToolMenu.ItemCount, "Set Trailing Stop")
		Handler.menuIdCancelStop = ToolMenu.InsertItem(ToolMenu.ItemCount, "Cancel Trailing Stop")
	End If
End If

' register our event handlers
If Not EventManager Is Nothing Then
	EventManager.RegisterHandlerMethod Handler, "OnMenuItemSelected"
	EventManager.RegisterHandlerMethod Handler, "OnTickerUpdated"
Else
	'Application.DebugTrace "Could not get EventManager object"
End If

' create the "Trailing Stop" custom column and associate it with the _TrailingStopComment custom attribute
If Not ViewManager Is Nothing Then
	ViewManager.CreateMemoColumn "Trailing Stop", "_TrailingStopComment", True
Else
	'Application.DebugTrace "Could not get ViewManager object"
End If

]]>