Getting prices and volume
This is a bit difficult to answer, because you did not share code sample that fully type-checks (and so it is hard to make sure the answer is correct). However, I think you're very close. When refactoring two similar functions, you just need to abstract out the bits that differ.

In your case, there are two places:


One is the function that is used to retrieve the data (either getPrices or getVolumes) 
Second is the projection that is used when triggering the event (either item or item.Price)


If you take these two operations as functions, then you can write the following:

open System

type IID = 
  abstract member ID : int64 

let Publish (dataRetriever:TimeSpan -&gt; list&lt;#IID&gt;) valueSelector time ID (polling:float) =  
  let sync = System.Threading.SynchronizationContext.Current 
  let obs = new Event&lt;int&gt;()  
  let raiseEvent (value:int) = sync.Post((fun _ -&gt; obs.Trigger(value)), null)   
  let interval = TimeSpan.FromSeconds(polling) 
  let rec loop nextTime= async {  
    // Generate next value (on the GUI thread)     
    dataRetriever nextTime 
    |&gt; List.filter (fun item -&gt; item.ID = ID) 
    |&gt; List.iter (fun item -&gt; raiseEvent (valueSelector item))                         
    // Wait some short time 
    do! Async.Sleep(1000) 
    // Continue looping 
    do! loop (nextTime.Add(interval)) } 
  loop time |&gt; Async.Start 
  obs.Publish 


The type annotation TimeSpan -&gt; list&lt;#IID&gt; is interesting. It says that the argument is a function that returns a list of some values that implement the IID interface - but it turns this type into a generic type argument that is then passed to the other function (valueSelector), so when you use the function, the compiler knows that the argument of valueSelector has the same type as the thing that you obtain from dataRetriever. The annotation allows you to write item.ID in the filtering function.

The two functions can now be defined as follows:

let Prices = Publish getPrices (fun price -&gt; price.Price)
let Volumes = Publish getVolumes id