RxSwift observable creation which takes the last value of the stream itself - rxjs

I am trying to use RxSwift to calculate SMA(simple moving average) and EMA(exponentially weighted moving average)
The setup is like below, the methods take the close price stream as input Observable<Double>. so every time if there is a new close price being emitted, the sma obervable will emit a new calculated value to the stream
I finished the SMA version, which is working fine
func sma(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
let bag = DisposeBag()
return Observable<Double?>.create { observer -> Disposable in
source.scan([]) { Array($0 + [$1].suffix(length)) }.subscribe(onNext: { value in
if value.count < length {
observer.onNext(nil)
} else {
observer.onNext(value.reduce(0.0, { $0 + $1 / Double(length) }))
}
}).disposed(by: bag)
return Disposables.create()
}
}
But the EMA formula is a bit complex
https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
the formula involve the previous EMA value.
I do not have clear idea how I can get the stream last value inside a Observable creation block :thinking
below is the code I tried to implement, but .withLatestFrom(ema(source, length)) did not work out
func ema(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
let bag = DisposeBag()
return Observable<Double?>.create { observer -> Disposable in
source.scan([]) { Array($0 + [$1].suffix(length)) }.withLatestFrom(ema(source, length)) { return ($0, $1) }
.subscribe(onNext: { value in
let alpha: Double = Double(2) / Double(length + 1)
let src = value.0
var sum: Double? = 0.0
let sum1 = value.1
sum = na(sum1) ? sma(src, length) : alpha * src.last! + (1 - alpha) * nz(sum1)
observer.onNext(sum)
}).disposed(by: bag)
return Disposables.create()
}
}
any help is greatly appreciated :pray

First let's cleanup your sma operator. You are creating dispose bags inside the function which is inappropriate. The subscribe returns a disposable and the create's closure needs to return a disposable. Just return the subscribe's disposable...
func sma(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
Observable<Double?>.create { observer -> Disposable in
source
.scan([]) { Array($0 + [$1].suffix(length)) }
.subscribe(onNext: { value in
if value.count < length {
observer.onNext(nil)
} else {
observer.onNext(value.reduce(0.0, { $0 + $1 / Double(length) }))
}
})
}
}
But since you are outputting the same number of events as you input, we can simplify even more. Whenever you are outputting the same number of events as you input, think map.
func sma(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
source
.scan([]) { Array($0 + [$1].suffix(length)) }
.map { value in
if value.count < length {
return nil
} else {
return value.reduce(0.0, { $0 + $1 / Double(length) })
}
}
}
And whenever you only have one Observable as input, consider making it an extension on the Observable type so it can be easily inserted into a chain...
extension ObservableType where Element == Double {
func sma(_ length: Int) -> Observable<Double?> {
scan([]) { Array($0 + [$1].suffix(length)) }
.map { $0.count < length ? nil : $0.reduce(0.0, { $0 + $1 / Double(length) }) }
}
}
Now that we have done all that, let's tackle your actual question. First express your formula as a function...
func getEMA(prices: [Double], k: Double? = nil) -> Double {
guard !prices.isEmpty else { return 0 }
let k = k ?? Double(2 / (prices.count + 1))
return prices[0] * k + getEMA(prices: prices.suffix(prices.count - 1), k: k) * (1 - k)
}
The above should be easy to test using some sample values. I'll leave you to do that. Once we have the above, we can use the same pattern you used for your sma to create the operator:
extension ObservableType where Element == Double {
func ema(_ length: Int) -> Observable<Double?> {
scan([]) { Array([$1] + $0).suffix(length) } // put the most recent price in front to correctly handle the formula
.map { $0.count < length ? nil : getEMA(prices: $0) }
}
}

I found a solution (not sure if its the cleanest way)
which is to create a BehaviourRelay inside the function declaration while outside of the Observable.create block, which keeps a local copy of the latest EMA calculated.
in this way, it does not need function's consumer to dependency inject an Observable nor having a complex stream transformation.
Below is the EMA(exponentially weighted moving average) implementation using RxSwift
func ema(_ source: Observable<Double>, _ length: Int) -> Observable<Double?> {
let bag = DisposeBag()
let lastEMA: BehaviorRelay<Double?> = BehaviorRelay.init(value: nil)
return Observable<Double?>.create { observer -> Disposable in
source.scan([]) { Array($0 + [$1].suffix(length)) }
.subscribe(onNext: { value in
let alpha: Double = Double(2) / Double(length + 1)
let src = value
var sum: Double? = 0.0
sum = na(lastEMA.value) ? sma(src, length) : alpha * src.last! + (1 - alpha) * nz(lastEMA.value)
observer.onNext(sum)
lastEMA.accept(sum)
}).disposed(by: bag)
return Disposables.create()
}
}
Remarks:
na and nz are method copied from TradingView pinescript
https://www.tradingview.com/pine-script-reference/#var_na
https://www.tradingview.com/pine-script-reference/#fun_nz
https://www.tradingview.com/pine-script-reference/#fun_ema

Related

In SwiftUI how do I animate changes one at a time when they occur in a called method?

Although I get an animation when I tap the button, it's not the animation I want.
The entire view is being replaced at once, but I want to see each element change in sequence. I tried in both the parent view and in the called method. Neither produces the desired result.
(this is a simplified version of the original code)
import SwiftUI
struct SequencedCell: Identifiable {
let id = UUID()
var value: Int
mutating func addOne() {
value += 1
}
}
struct AQTwo: View {
#State var cells: [SequencedCell]
init() {
_cells = State(initialValue: (0 ..< 12).map { SequencedCell(value: $0) })
}
var body: some View {
VStack {
Spacer()
Button("+") {
sequencingMethod(items: $cells)
}
.font(.largeTitle)
Spacer()
HStack {
ForEach(Array(cells.enumerated()), id: \.1.id) { index, item in
// withAnimation(.linear(duration: 4)) {
Text("\(item.value)").tag(index)
// }
}
}
Spacer()
}
}
func sequencingMethod(items: Binding<[SequencedCell]>) {
for cell in items {
withAnimation(.linear(duration: 4)) {
cell.wrappedValue = SequencedCell(value: cell.wrappedValue.value + 1)
// cell.wrappedValue.addOne()
}
}
}
}
struct AQTwoPreview: PreviewProvider {
static var previews: some View {
AQTwo()
}
}
So I want the 0 to turn into a 1, the 1 then turn into a 2, etc.
Edit:
Even though I have accepted an answer, it answered my question, but didn't solve my issue.
I can't use DispatchQueue.main.asyncAfter because the value I am updating is an inout parameter and it makes the compiler unhappy:
Escaping closure captures 'inout' parameter 'grid'
So I tried Malcolm's (malhal) suggestion to use delay, but everything happens immediately with no sequential animation (the entire block of updated items animate as one)
Here's the recursive method I am calling:
static func recursiveAlgorithm(targetFill fillValue: Int, in grid: inout [[CellItem]],
at point: (x: Int, y: Int), originalFill: Int? = nil, delay: TimeInterval) -> [[CellItem]] {
/// make sure the point is on the board (or return)
guard isValidPlacement(point) else { return grid }
/// the first time this is called we don't have `originalFill`
/// so we read it from the starting point
let tick = delay + 0.2
//AnimationTimer.shared.tick()
let startValue = originalFill ?? grid[point.x][point.y].value
if grid[point.x][point.y].value == startValue {
withAnimation(.linear(duration: 0.1).delay(tick)) {
grid[point.x][point.y].value = fillValue
}
_ = recursiveAlgorithm(targetFill: fillValue, in: &grid, at: (point.x, point.y - 1), originalFill: startValue, delay: tick)
_ = recursiveAlgorithm(targetFill: fillValue, in: &grid, at: (point.x, point.y + 1), originalFill: startValue, delay: tick)
_ = recursiveAlgorithm(targetFill: fillValue, in: &grid, at: (point.x - 1, point.y), originalFill: startValue, delay: tick)
_ = recursiveAlgorithm(targetFill: fillValue, in: &grid, at: (point.x + 1, point.y), originalFill: startValue, delay: tick)
}
return grid
}
Further comments/suggestions are welcome, as I continue to wrestle with this.
As mentioned in the comments, the lowest-tech version is probably just using a DisatpchQueue.main.asyncAfter call:
func sequencingMethod(items: Binding<[SequencedCell]>) {
var wait: TimeInterval = 0.0
for cell in items {
DispatchQueue.main.asyncAfter(deadline: .now() + wait) {
withAnimation(.linear(duration: 1)) {
cell.wrappedValue = SequencedCell(value: cell.wrappedValue.value + 1)
}
}
wait += 1.0
}
}
You could use delay(_:) for that, e.g.
func sequencingMethod(items: Binding<[SequencedCell]>) {
var delayDuration = 0.0
for cell in items {
withAnimation(.linear(duration: 4).delay(delayDuration)) {
cell.wrappedValue = SequencedCell(value: cell.wrappedValue.value + 1)
}
delayDuration += 0.5
}
}

How to increase or decrease the probability of an item of an array being picked

Lets say I have an array of numbers like this:
// Create Array Of Numbers
let numbers = ["1","2","3","4","5"]
If I want to print a random number from the array, I can do something like:
pickedNumber = Int.random(in: 0...numbers.count - 1)
The above line will return a random value from my array.
What I would like to do is, set a probability for each value in the array. For example:
- Chance of 1 being picked at 10%
- Chance of 2 being picked at 20%
- Chance of 3 being picked at 30%
- Chance of 4 being picked at 35%
- Chance of 5 being picked at 5%
What's the best approach for this? Any guidance or advice would be appreciated. This problem I am facing is in swiftUI.
more of a mathematical question than an UI question, but nevertheless:
let probs = [
1 : 10,
2 : 20,
3 : 30,
4 : 35,
5 : 5
]
func randomWithProbability(distribution: [Int : Int]) -> Int {
var distributionArray: [Int] = []
distribution.forEach { (key: Int, value: Int) in
let new = Array(repeating: key, count: value)
distributionArray.append(contentsOf: new)
}
let r = Int.random(in: 0..<distributionArray.count)
return distributionArray[r]
}
and to prove it:
struct ContentView: View {
private var results: [Int]
init() {
results = [0,0,0,0,0]
for _ in 0..<1000 {
let i = randomWithProbability(distribution: probs)
results[i-1] += 1
}
}
var body: some View {
VStack(alignment: .leading) {
ForEach(results.indices) { i in
HStack {
Text("\(i)")
Color.blue
.frame(width: CGFloat(results[i]), height: 40)
}
}
}
}
}
Create normalized weighted ranges.
[ 0.0..<0.1,
0.1..<0.3,
0.3..<0.6,
0.6..<0.95,
0.95..<1.0
]
let normalizedWeightedRanges = [10, 20, 30, 35, 5].normalizedWeightedRanges
import Algorithms
public extension Sequence where Element: FloatingPoint {
/// Normalized (`0..<1`) representations of the elements' weights within their sum.
var normalizedWeightedRanges: [Range<Element>] {
guard let sum = sum else {
return []
}
return .init(
reductions(0..<0) {
$0.upperBound..<$1 / sum + $0.upperBound
}.dropFirst()
)
}
}
public extension Sequence where Element: AdditiveArithmetic {
var sum: Element? { reduce(+) }
}
public extension Sequence {
/// - Returns: `nil` If the sequence has no elements, instead of an "initial result".
func reduce(
_ nextPartialResult: (Element, Element) throws -> Element
) rethrows -> Element? {
var iterator = makeIterator()
return try iterator.next().map { first in
try IteratorSequence(iterator).reduce(first, nextPartialResult)
}
}
}
Sample. (Binary search would be better than firstIndex.)
/// - precondition: `normalizedWeightedRanges` is the result of `Sequence.normalizedWeightedRanges`
func randomIndex<Float: BinaryFloatingPoint>(
inNormalizedWeightedRanges normalizedWeightedRanges: [Range<Float>]
) -> Int
where Float.RawSignificand: FixedWidthInteger {
normalizedWeightedRanges.firstIndex { [random = Float.random(in: 0..<1)] in
$0.contains(random)
}!
}
more efficient:
let results = getResults(input:[0.1, 0.3, 0.6, 0.95,1])
func getResults(input: [Float]) -> [Int] {
var results: [Int] = [Int](0..<input.count)
for _ in 0..<iteration {
let random = Float.random(in: 0...1)
for i in input.enumerated() {
if random <= i.element {
results[i.offset] += 1
break
}
}
}
return results
}
Add 1 10 times to your array, 2 20 times, and so on. Your Array will have 100 elements so you will control the probability for each element.
If your values are always going to be multiples of 5% you can use an array of 20 elements and add a proportional number of values.

swift function or closure with pre-filled parameter

I have a class that takes a completion handler. Can I pre-fill some the parameters? The completion handler is a function itself rather than a closure.
func completionHandler(value: Int, value2: Int)
{
print(value + value2)
}
func run() {
let handler = completionHandler
handler(9, value2: 7) //runs the handler
someinstance.handler = handler //someinstance will eventually run the handler
let handler2 = completionHandler(9) //is this possible?
someinstance2.handler = handler2 //is this possible?
someinstance3.handler = { a,b in return a+b } //also fine
}
You could, technically, define a handler for you completion handler, for cases when you want to make use of a default value for value or value2 in completionHandler.
func completionHandler(value: Int, _ value2: Int) {
print(value + value2)
}
func defaultValueHandler(defaultValue: Int? = nil, defaultValue2: Int? = nil) -> ((Int) -> ()) {
if let defaultValue2 = defaultValue2 {
return { value in completionHandler(value, defaultValue2) }
}
else if let defaultValue = defaultValue {
return { value in completionHandler(defaultValue, value) }
}
return { _ in print("Invalid use: supply a single non-nil default value.") }
}
var handler = defaultValueHandler(9) // default value for 'value'
handler(5) // calls foo(9, 5), prints 14
handler = defaultValueHandler(nil, defaultValue2: 11) // default value for 'value2'
handler(5) // calls foo(5, 11), prints 16
The use of this is, for your case, probably limited in practice. The handler closure instance above will be of type (Int) -> () as compared to e.g. completionHandler function which is of type (Int, Int) -> (). So if someinstance.handler (in your example) expects the latter, you'll be in trouble.
Now, you could modify defaultValueHandler(..) to return closures of type (Int, Int) -> (), but then you'll need to supply calls to the resulting handling closure with two arguments, where one argument will be ignored in favour of the default value you supplied when assigning a closure to the handler. Again, this technically possibly, but will most likely just confuse whomever codes, and lives near the subject of "troll coding" (e.g. not-so-appriciated 1st april insertion into the code of a colleague, "handler(2,2) == 4 // false ?!?"). Anyway:
func completionHandler(value: Int, _ value2: Int) {
print(value + value2)
}
func defaultValueHandler(defaultValue: Int? = nil, defaultValue2: Int? = nil) -> ((Int, Int) -> ()) {
if let defaultValue2 = defaultValue2 {
if defaultValue == nil {
return { value, _ in completionHandler(value, defaultValue2) }
}
}
else if let defaultValue = defaultValue {
return { _, value2 in completionHandler(defaultValue, value2) }
}
return { _ in print("Invalid use: supply a single non-nil default value.") }
}
var handler = defaultValueHandler(9)
handler(0,5) // ignores first parameter '0', calls foo(9, 5), prints 14
handler = defaultValueHandler(nil, defaultValue2: 11)
handler(5,0) // ignores second parameter '0', calls foo(5, 11), prints 16

Swift: filter protocol array by comparing types

(first post)
usually im able to find answers here or elsewhere but no luck this time =(
Question: in Swift, how do you filter an array that is of a protocol type by an implementing type supplied as a function parameter?
protocol Aprotocol {
var number:Int { get set }
}
class Aclass: Aprotocol {
var number = 1
}
class AnotherClass: Aprotocol {
var number = 1
}
var array:[Aprotocol] = [ Aclass(), AnotherClass(), Aclass() ]
func foo (parameter:Aprotocol) -> Int {
return array.filter({ /* p in p.self == parameter.self */ }).count
}
var bar:Aprotocol = // Aclass() or AnotherClass()
var result:Int = foo(bar) // should return 2 or 1, depending on bar type
maybe this is not the right approach at all?
thanks!
Here is what I think you want:
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == parameter.dynamicType
}.count
But I recommend this, which does the same, but without the useless instance of Aclass() which is passed in the answer on the top. Also this way is faster:
func foo <T: Aprotocol>(type: T.Type) -> Int {
return array.filter { (element: Aprotocol) -> Bool in
element.dynamicType == type
}.count
}
var result:Int = foo(Aclass)
The dynamicType will return the Type of an instance
Very easy:
return array.filter({ parameter.number == $0.number }).count
Kametrixoms solution works (if you use "is T" instead of "== type") but in my case, since i didnt know which implementing class was going to call it, had to go with this solution:
protocol Aprotocol: AnyObject {
var number:Int { get set }
}
class func foo(parameter: AnyObject) -> Int {
return array.filter ({ (element: Aprotocol) -> Bool in
object_getClassName(element) == object_getClassName(parameter)
}).count
}

computed setter for a subscript of an array in Swift [duplicate]

This question already has answers here:
Shorthand setter declaration for a subscript of an array in Swift
(2 answers)
Closed 8 years ago.
To keep it short, what I want to achieve is for example:
var actions: [String]{
get{
if (_actions==nil){
_actions = []
}
return _actions!
}
set{
_actions = newValue
}
subscript(index:Int) -> String{
set {
assert(index<_actions.count && index>=0, "Index out of range")
_actions[index] = newValue
}
}
}
I know subscript isn't an accessor for array, but then what is the most convinient alternative to do just that?
I truly appreciate for succinct answers if possible! Thank you very much!
Edit:
To extend my explanation for #jrturton,
What I am trying to achieve is whenever actions[i] is set to a newValue, I would like to do some extra computations, such as repositioning actions[i]'s respective subview.
But if i say actions[3] = "randomMethod", the computed setter for the entire array will get called. Right? So I'd like to find a way so that when actions[3] is set to a newValue, a function repositionView(3) can get called, for example.
I know other ways to do it, but my question simply askes if there is a more convinient way, like the example above: a computed setter, to do what I want?
Edit 2:
To show #Vatsal Manot what I truly mean, I removed getter for subscript, and here is a complete example.swift(which wont run due to error):
import UIKit
import Foundation
class DWActionsSubmenu: UIView{
var actions: [DWAction]{
get{
if (_actions==nil){
_actions = []
}
return _actions!
}
set{
_actions = newValue
}
subscript(index:Int) -> DWAction{
set {
assert(index<_actions.count && index>=0, "Index out of range")
_actions[index] = newValue
a()
}
}
}
var _actions: [DWAction]?
init(actions:[DWAction]?){
super.init()
_actions = actions
}
required init(coder aDecoder: NSCoder) {
super.init(coder:aDecoder)
}
func a(){
}
}
I'd wrap your actions list in a custom class that you can then access via subscripting. You can then add a block to be run whenever a subscripted member is set:
class ActionList {
private var actions = [String]()
var actionDidChange : ((Int) -> ())?
subscript(actionIndex:Int) -> String {
get {
return actions[actionIndex]
}
set {
actions[actionIndex] = newValue
if let actionDidChange = actionDidChange {
actionDidChange(actionIndex)
}
}
}
func addAction(action: String) {
actions.append(action)
}
func addActions(newActions:[String]) {
actions += newActions
}
}
Usage (in a playground):
let actionList = ActionList()
actionList.actionDidChange = {
actionIndex in
println("Action \(actionIndex) did change")
}
actionList.addActions(["One", "Two", "Three"])
actionList[2] = "New"
// Prints "Action 2 did change"
The following should work:
var actions: [String] = []
subscript(index:Int) -> String
{
get
{
assert(index < actions.count && index >= 0, "Index out of range")
return actions[index]
}
set(newValue)
{
assert(index < actions.count && index >= 0, "Index out of range")
actions[index] = newValue
}
}

Resources