비트코인 가격 표시기 만들기

Learning functional programming

Advanced track



이 시리즈에서는 작은 응용 프로그램을 빌드하여 함수형 프로그래밍의 기본 개념과 도구를 살펴보고자 합니다.

스트림





스트림은 데이터에 액세스하고 처리하는 방식을 추상화하는 개념적 장치입니다. 핵심에 있는 스트림은 일련의 데이터일 뿐입니다. 그러나 배열이나 목록과 달리 스트림에는 반드시 시작과 끝이 있는 것은 아닙니다.

실생활에서 우리는 스트림의 몇 가지 예를 가지고 있습니다. 예를 들어 Bitcoin 가격에 대한 시세 표시기. 분명히 시간이 지정된 데이터 시퀀스이기 때문에 스트림입니다. 시작은 있지만(비트코인이 생성되었을 때) 끝나지 않습니다.

비트코인 가격 표시기 만들기



이번 호에서는 화면에서 실행되는 BTC 티커를 만들 것입니다. 이렇게 하면 매수 시점과 매도 시점을 항상 알 수 있습니다.

설계





2초 안에 제도할 수 있는 간단한 디자인이 위에 스케치된 것입니다. 일부 API를 선택하고 출력을 구문 분석하고 숫자로 변환한 다음 마지막으로 화면(또는 복고풍인 경우 물리적 시세 표시기)에 인쇄합니다.



프로그램 작성



프로그램의 첫 번째 초안은 다음과 같을 수 있습니다.

ZStream
  .repeat("100.000") // generate some fake data
  .take(3) // let's not overload
  .map(identity) // placeholder for parsing
  .map(priceString => BigDecimal(priceString))
  .foreach(price =>
    putStrLn(
      s"BTC-EUR: ${price.setScale(2, BigDecimal.RoundingMode.UP)}"
    )
  )


계속 진행할 수 있으며 launch this . 첫 번째 줄에서 우리는 ZStream 객체를 얻고 있으며, 여기에는 우리가 전달하는 모든 것을 무한히 생성하는 repeat 메서드가 포함되어 있습니다. 이 경우에는 문자열입니다. 우리는 그것을 3개의 문자열로 제한합니다. 그렇지 않으면 기계에 과부하가 걸리고 멈추지 않을 것입니다. 지금은 구문 분석이 ID 기능으로 가장됩니다. 그런 다음 BigDecimal 구문 분석 기능을 활용하여 작업할 숫자를 갖습니다. 마지막으로 단말 방식인 foreach 방식을 사용한다. 형식이 잘 지정된 가격 표시를 화면에 인쇄하여 스트림을 마무리합니다.

반올림을 제어하는 ​​데 관심이 없다면 BigDecimal로의 변환을 건너뛸 수도 있습니다.

ZStream
  .repeat("100.000")
  .take(3)
  .map(identity)
  .foreach(price => putStrLn(s"BTC-EUR: $price"))


이제 우리는 좋은 API를 찾아갑니다. 요리 TV 쇼에서처럼 이미 해봤지만 직접 찾아보고 추천합니다 ProgrammableWeb .

아주 기본적인 Kraken public API을 사용하겠습니다. 다음 형식의 json을 반환합니다.

{
    "error": [],
    "result": {
        "XXBTZEUR": {
            ... other stuff
            "c": "last trade price",
            ... other stuff
        }
    }


우리는 마지막 거래 가격인 현재 가격에 관심이 있습니다. 이것을 추출하기 위해 json 파서를 사용할 수 있습니다. 그러나 그렇게 하면 벌레가 생길 수 있으므로 정규식을 사용하겠습니다.


def parsePrice(json: String): String = {
  val regex = raw"""(?s).*"c":\["([0-9.]+).*""".r
  json match {
    case regex(price) => price
  }
}


따라서 구문 분석 단계가 있으므로 마침내 실제로 API를 호출해야 합니다. 다시 말하지만 우리가 사용할 수 있는 매우 멋진 http 클라이언트가 있습니다. 대신 단순화를 위해 scala 내장 클라이언트를 사용합니다.

val tickerURLCall: Task[String] = IO(
  io.Source
    .fromURL("https://api.kraken.com/0/public/Ticker?pair=BTCEUR")
    .mkString
)


이제 프로그램에 모든 것을 함께 넣을 수 있습니다. 가짜 데이터 대신 tickerURLCall를 사용하고 ID 대신 priceParce를 사용합니다.

  val program: ZIO[Console with Clock, Throwable, Unit] = ZStream
    .repeatEffect(tickerURLCall)
    .throttleShape(1, 5.seconds)(_ => 1) // let's slow down
    .map(parsePrice)
    .foreach(price =>
      putStrLn(
        s"BTC-EUR: $price"
      )
    )


노드throttleShape 기능이 추가되었습니다. API를 최대한 빠르게 호출하는 것이 아니라 일정한 느린 속도를 원하기 때문입니다. 코드는 5초마다 1번 호출한다고 말합니다. 두 번째 괄호 쌍에 제공하는 함수는 결과의 가중치를 계산하는 함수입니다(그에 따라 스로틀을 형성하기 위해) 모든 응답을 1로 간주합니다.

이 마지막 기능은 페이지 매김이 있고 각 페이지에 얼마나 많은 항목이 있는지 모르는 경우에 유용합니다. 분당 10개의 항목을 출력하는 스트림을 생성할 수 있으며 때로는 소스 API에 대한 호출이 더 많이(또는 더 적게) 반환됩니다. 그러면 보상을 위해 API가 더 느리게(또는 더 빠르게) 호출됩니다.

또한 스로틀링이 적용되었으므로 이제 take(3)로 틱 수를 제한할 필요가 없습니다.

test the bitcoin ticker on Scastie 좋아하는 통화 쌍과 좋아하는 반올림을 표시하도록 편집해야 합니다.

좋은 웹페이지 즐겨찾기