[
  {
    "path": ".gitignore",
    "content": "#---------以下为通用配置BEGIN------\n\n# 操作系统忽略文件\n# OSX\n*.DS_Store\n# Windows thumbnail db\nThumbs.db\n\n## AndroidStudio IDE忽略文件\n# Intellij\n*.iml\n.idea/\n# Android Studio captures folder\ncaptures/\n# Android Studio Navigation editor temp files\n.navigation/\n\n## gradle忽略文件\n# Gradle files\n.gradle/\ngradle/\ngradlew\ngradlew.bat\n\n## sdk配置文件\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n## 编译生成的文件\n# Generated files\nbin/\ngen/\nout/\nbuild/\n*.dex\n## *.apk\n*.ap_\n*.class\n\n## 日志文件\n# Log Files\n*.log\n#---------以上为通用配置END--------\n\n\n#--------- 根据需求个性化配置---------\n\n# Keystore files\n# *.jks\n\n\n## 第三方\n\n# bugly\n*.txt\n\n\n\n# note\n# .ignore不起作用解决方案\n# git rm -r --cached .\n# git add .\n# git commit -m \"update .ignore\""
  },
  {
    "path": "README.md",
    "content": "## FinancialCustomerView\n* 本项目会对金融交易软件中存在的各种View进行模仿绘制\n* 提供详细的实现思路\n* 收集整理相关算法、文档以及专业资料\n* 开源库不依赖第三方，继承系统View实现\n* 提供完整Demo\n*  [参考文档](https://github.com/Tophold/FinancialCustomerView/tree/master/%E8%B5%84%E6%96%99%E4%B8%8E%E6%96%87%E6%A1%A3)\n\n## 号外\n1. [MPAndroidChartWrapper](https://github.com/scsfwgy/MPAndroidChartWrapper)【开发完善中...】高度封装MPAndroidChart,提供开箱即用的MPAndroidChart。\n两大原则：1.不修改MPAndroidChart源码，只继承封装原有功能实现扩展。2. 开箱即用。目标：可商用。\n2. 商用k线图**推荐**使用[MPAndroidChartWrapper](https://github.com/scsfwgy/MPAndroidChartWrapper)，让您几行代码实现一个商用级别k线图。\n\n#### 目录\n1. ``com.tophold.trade.view.fund.FundView`` 仿蚂蚁金服基金走势图\n2. ``com.tophold.trade.view.kview.KView`` k线走势图\n3. ``com.tophold.trade.view.pie.PieChartView`` 饼图\n4. ``com.tophold.trade.view.seekbar.DoubleThumbSeekBar``  双Thumb自定义进度条\n\n#### com.tophold.trade.view.fund.FundView\n* 仿蚂蚁金服基金走势图，支持长按查看指定数据，可以据此扩展出各种简单的资金走势图。KView的思路来自于此。\n\n![](https://github.com/scsfwgy/FinancialCustomerView/raw/master/img/v1.1_img_nopress.png)\n\n![](https://github.com/scsfwgy/FinancialCustomerView/raw/master/img/v1.1_img_press.png)\n\n#### com.tophold.trade.view.kview.KView\n* k线走势图，支持主图+副图+量图\n* 主图支持缩放、长按十字、滑动等各种手势操作；支持显示最小、最大值；指标支持：ma、boll、ma+boll;图形类别支持分时图、蜡烛图\n* 副图支持指标：macd、kdj、rsi\n* 量图支持：量、ma(5,10)\n*\n\n![](https://raw.githubusercontent.com/Tophold/FinancialCustomerView/master/img/vol_huobi_eos.png)\n\n![](https://raw.githubusercontent.com/Tophold/FinancialCustomerView/master/img/vol_huobi_eos_press.png)\n\n#### com.tophold.trade.view.pie.PieChartView\n* 饼图，加载动画、特定指示图\n\n![](https://camo.githubusercontent.com/d345e80888d09007764b575932a7ede0ba368953/687474703a2f2f6f373175686f6b67662e626b742e636c6f7564646e2e636f6d2f31353331383135393530313831372e6a7067)\n\n#### com.tophold.trade.view.seekbar.DoubleThumbSeekBar\n* 双Thumb自定义进度条，可以高度定制化\n* 支持单、双thumb\n* 支持从左、右开始最小值（和滑动方向无关）\n* 两个thumb可以任意设置开始方向以及起始位置\n* 支持数据回调\n* 具体使用参看Demo\n\n![](https://raw.githubusercontent.com/Tophold/FinancialCustomerView/master/img/DoubleThumbSeekBar.png)\n\n#### 其它\n* [天厚投资](https://www.tophold.com/)\n* [MPAndroidChart](https://github.com/PhilJay/MPAndroidChart)\n\n\n\n\n"
  },
  {
    "path": "README_en.md",
    "content": "# FinancialCustomerView\n\n## Introduce\n> This project will simulate the various views in financial transaction software, provide detailed implementation ideas, and collect relevant algorithms, documents and professional materials.\n\n## Significance\n> May our developers to say, have very mature third party framework, why return to oneself to realize?\n\n* Knowing how to write and draw, it is more convenient to extend the third library graphics library.\n* Understand the principle of implementation, if the third parties can not achieve, you can write one in a leisurely way.\n* There are many kinds of algorithms and various indicators in financial transactions, but there are few related information on the Internet. I hope can give a little help to financial related developers.\n* Knowing it, knowing it is so.\n\n## Demo\n* impression drawing：[impression drawing](https://github.com/scsfwgy/FinancialCustomerView/blob/master/%E8%B5%84%E6%96%99%E4%B8%8E%E6%96%87%E6%A1%A3/%E6%95%88%E6%9E%9C%E5%9B%BE%E5%92%8C%E8%BF%9B%E5%BA%A6.md)\n* demo apk:[demo_apk](https://github.com/scsfwgy/FinancialCustomerView/tree/master/apk)\n\n## Reference material and blogs\n* reference material and blogs：[reference material and blogs](https://github.com/scsfwgy/FinancialCustomerView/tree/master/%E8%B5%84%E6%96%99%E4%B8%8E%E6%96%87%E6%A1%A3)\n\n## Schedule\n* Completed：The FundView has developed in the master branch.\n* Completed：The TimeSharingView has developed in the master branch.\n* Completed：The CandleView（including MA、BOLL）has developed in the master branch.\n* Completed：The code refactoring has completed in the master branch. The code is refactoring in the later period.\n* being developed：The MinorView is being developed in the feature_minor branch.\n* plan：Verify the accuracy of the data (proofread data with On-line app).\n* plan：Test availability using open API in a real environment.\n* plan：Simulating real use，switching timesharing、5m、15m、30m、1h、1d、1w、1m。\n\n## Contribution\n* new branch，PR。\n\n## Famous third party graphic library\n* MPAndroidChart：[https://github.com/PhilJay/MPAndroidChart](https://github.com/PhilJay/MPAndroidChart)\n* AndroidCharts：[https://github.com/HackPlan/AndroidCharts](https://github.com/HackPlan/AndroidCharts)\n* Android-Charts：[https://github.com/limccn/Android-Charts](https://github.com/limccn/Android-Charts)\n\n\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\n/**获取git count HEAD，可以根据该值回退版本*/\ndef getMyVersionCode() {\n    Process process = \"git rev-list --count HEAD\".execute()\n    process.waitFor()\n    int cccc = process.getText().toInteger()\n    return cccc\n}\n\nandroid {\n    compileSdkVersion 28\n    defaultConfig {\n        applicationId \"com.tophold.example\"\n        minSdkVersion 17\n        targetSdkVersion 28\n        versionCode getMyVersionCode() as int//查询versioncode即可找到对应git历史\n        versionName \"0.0.1\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n\n\n    }\n\n    signingConfigs {\n        //debug模式下签名的设置，这里的配置主要用于脚本运行。对于采用图形界面构建测不起效。\n        debug {\n            storeFile file(project.debug_storeFile)\n            storePassword project.debug_storePassword\n            keyAlias project.debug_keyAlias\n            keyPassword project.debug_keyPassword\n            v1SigningEnabled true\n            v2SigningEnabled true\n        }\n\n        beta {\n            storeFile file(project.debug_storeFile)\n            storePassword project.debug_storePassword\n            keyAlias project.debug_keyAlias\n            keyPassword project.debug_keyPassword\n            v1SigningEnabled true\n            v2SigningEnabled true\n        }\n\n        release {\n            storeFile file(project.release_storeFile)\n            storePassword project.release_storePassword\n            keyAlias project.release_keyAlias\n            keyPassword project.release_keyPassword\n            v1SigningEnabled true\n            v2SigningEnabled true\n        }\n    }\n\n    buildTypes {\n        //平时开发使用\n        debug {\n            // 显示Log\n            buildConfigField \"boolean\", \"LOG_DEBUG\", \"true\"\n            shrinkResources false\n            minifyEnabled false\n            zipAlignEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n            //versionName的后缀\n            versionNameSuffix \"_debug\"\n            //appId后缀，加一个后缀保证各个版本（debug、beta、release可以共存）\n            applicationIdSuffix \".debug\"\n            //签名选择\n            signingConfig signingConfigs.debug\n            //动态修改应用的名字和图标\n            manifestPlaceholders = [app_names: \"金融View_debug\"]\n            debuggable true\n        }\n\n        //内侧使用\n        beta {\n            // 显示Log\n            buildConfigField \"boolean\", \"LOG_DEBUG\", \"true\"\n            shrinkResources false\n            minifyEnabled false\n            zipAlignEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n            //versionName的后缀\n            versionNameSuffix \"_beta\"\n            //appId后缀\n            applicationIdSuffix \".beta\"\n            //签名选择\n            signingConfig signingConfigs.beta\n            manifestPlaceholders = [app_names: \"金融View_beta\"]\n            debuggable true\n        }\n\n        //正式版本\n        release {\n            //不显示log信息\n            buildConfigField \"boolean\", \"LOG_DEBUG\", \"false\"\n            // 移除无用的resource文件\n            shrinkResources true\n            //混淆\n            minifyEnabled true\n            //压缩\n            zipAlignEnabled true\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n            //签名\n            signingConfig signingConfigs.release\n\n            manifestPlaceholders = [app_names: \"金融View\"]\n            debuggable true\n        }\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\n\ndependencies {\n    implementation fileTree(include: ['*.jar'], dir: 'libs')\n    implementation 'com.android.support:support-v4:28.0.0'\n    implementation 'com.android.support:recyclerview-v7:28.0.0'\n    implementation 'com.android.support:design:28.0.0'\n    implementation 'com.android.support.constraint:constraint-layout:1.1.3'\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'com.android.support.test:runner:1.0.2'\n    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'\n\n    implementation project(path: ':financiallib')\n\n    //rx2.0\n    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'\n    implementation 'io.reactivex.rxjava2:rxjava:2.2.8'\n    //api\n    implementation 'com.squareup.retrofit2:retrofit:2.5.0'\n    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'\n    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'\n    implementation 'com.squareup.okhttp3:okhttp:3.12.0'\n    implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'\n    /**https://github.com/CymChad/BaseRecyclerViewAdapterHelper:qucik recycle*/\n    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.49'\n    implementation 'org.greenrobot:eventbus:3.1.1'\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n}\n\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-android-extensions'\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "\n\n\n\n###########################正文####################################\n##这里是APP默认的混淆配置规则，和第三方没有关系。\n##这里禁止配置个性化、第三方库的混淆配置。\n##应用第三方库混淆规则配置请配置在最下方\"其它第三方\"模块。\n\n#指定代码的压缩级别\n-optimizationpasses 5\n\n#包明不混合大小写\n-dontusemixedcaseclassnames\n\n#不去忽略非公共的库类\n-dontskipnonpubliclibraryclasses\n\n #优化  不优化输入的类文件\n-dontoptimize\n\n #预校验\n-dontpreverify\n\n #混淆时是否记录日志\n-verbose\n\n # 混淆时所采用的算法\n-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*\n\n#保护注解\n-keepattributes *Annotation*\n\n# 保持哪些类不被混淆\n-keep public class * extends android.app.Fragment\n-keep public class * extends android.app.Activity\n-keep public class * extends android.app.Application\n-keep public class * extends android.app.Service\n-keep public class * extends android.content.BroadcastReceiver\n-keep public class * extends android.content.ContentProvider\n-keep public class * extends android.app.backup.BackupAgentHelper\n-keep public class * extends android.preference.Preference\n-keep public class com.android.vending.licensing.ILicensingService\n\n#如果引用了v4或者v7包\n-dontwarn android.support.**\n\n# support design\n#@link http://stackoverflow.com/a/31028536\n-dontwarn android.support.design.**\n-keep class android.support.design.** { *; }\n-keep interface android.support.design.** { *; }\n-keep public class android.support.design.R$* { *; }\n\n\n#忽略警告\n-ignorewarning\n\n##记录生成的日志数据,gradle build时在本项目根目录输出##\n#apk 包内所有 class 的内部结构\n-dump proguard/class_files.txt\n#未混淆的类和成员\n-printseeds proguard/seeds.txt\n#列出从 apk 中删除的代码\n-printusage proguard/unused.txt\n#混淆前后的映射\n-printmapping proguard/mapping.txt\n\n#保持 native 方法不被混淆\n-keepclasseswithmembernames class * {\n    native <methods>;\n}\n\n#保持自定义控件类不被混淆\n-keepclasseswithmembers class * {\n    public <init>(android.content.Context, android.util.AttributeSet);\n}\n-keepclassmembers class * extends android.app.Activity {\n   public void *(android.view.View);\n}\n\n-keep public class * extends android.view.View {\n    public <init>(android.content.Context);\n    public <init>(android.content.Context, android.util.AttributeSet);\n    public <init>(android.content.Context, android.util.AttributeSet, int);\n    public void set*(...);\n}\n\n#保持 Parcelable 不被混淆\n-keep class * implements android.os.Parcelable {\n  public static final android.os.Parcelable$Creator *;\n}\n\n#保持 Serializable 不被混淆\n-keepnames class * implements java.io.Serializable\n\n#保持 Serializable 不被混淆并且enum 类也不被混淆\n-keepclassmembers class * implements java.io.Serializable {\n    static final long serialVersionUID;\n    private static final java.io.ObjectStreamField[] serialPersistentFields;\n    !static !transient <fields>;\n    !private <fields>;\n    !private <methods>;\n    private void writeObject(java.io.ObjectOutputStream);\n    private void readObject(java.io.ObjectInputStream);\n    java.lang.Object writeReplace();\n    java.lang.Object readResolve();\n}\n\n#保持枚举 enum 类不被混淆\n-keepclassmembers enum * {\n  public static **[] values();\n  public static ** valueOf(java.lang.String);\n}\n\n-keepclassmembers class * {\n    public void *ButtonClicked(android.view.View);\n}\n\n#不混淆资源类\n-keepclassmembers class **.R$* {\n    public static <fields>;\n}\n\n#避免混淆泛型 如果混淆报错建议关掉\n-keepattributes Signature\n\n#移除Log类打印各个等级日志的代码，打正式包的时候可以做为禁log使用，这里可以作为禁止log打印的功能使用，另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制\n#-assumenosideeffects class android.util.Log {\n#    public static *** v(...);\n#    public static *** i(...);\n#    public static *** d(...);\n#    public static *** w(...);\n#    public static *** e(...);\n#}\n\n\n\n#################################################必备开发第三方################################\n# UI相关\n## https://github.com/JakeWharton/butterknife:butterknife\n-keep class butterknife.** { *; }\n-dontwarn butterknife.internal.**\n-keep class **$$ViewBinder { *; }\n-keepclasseswithmembernames class * {\n    @butterknife.* <fields>;\n}\n-keepclasseswithmembernames class * {\n    @butterknife.* <methods>;\n}\n\n## https://github.com/bumptech/glide:glide\n-keep public class * implements com.bumptech.glide.module.GlideModule\n-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {\n  **[] $VALUES;\n  public *;\n}\n\n## https://github.com/CymChad/BaseRecyclerViewAdapterHelper:recycle封装\n-keep class com.chad.library.adapter.** {\n*;\n}\n-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter\n-keep public class * extends com.chad.library.adapter.base.BaseViewHolder\n-keepclassmembers  class **$** extends com.chad.library.adapter.base.BaseViewHolder {\n     <init>(...);\n}\n\n## https://github.com/gyf-dev/ImmersionBarw:沉浸式*/\n-keep class com.gyf.barlibrary.* {*;}\n\n\n# 数据相关\n## https://github.com/greenrobot/EventBus:EventBus3.0混淆配置\n-keepattributes *Annotation*\n-keepclassmembers class ** {\n    @org.greenrobot.eventbus.Subscribe <methods>;\n}\n-keep enum org.greenrobot.eventbus.ThreadMode { *; }\n\n# Only required if you use AsyncExecutor\n-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {\n    <init>(java.lang.Throwable);\n}\n\n## https://github.com/google/gson：gson\n-keepattributes Signature\n# Gson specific classes\n-keep class sun.misc.Unsafe { *; }\n# Application classes that will be serialized/deserialized over Gson\n-keep class com.google.gson.** { *; }\n-keep class com.google.gson.stream.** { *; }\n\n## https://github.com/Blankj/AndroidUtilCode:安卓开发常用工具类\n-keep class com.blankj.utilcode.** { *; }\n-keepclassmembers class com.blankj.utilcode.** { *; }\n-dontwarn com.blankj.utilcode.**\n\n\n# APP运维\n#bugly\n-dontwarn com.tencent.bugly.**\n-keep public class com.tencent.bugly.**{*;}\n\n# Umeng\n-keepclassmembers class * {\n   public <init> (org.json.JSONObject);\n}\n-keep public class wgyscsf.quickapp.R$*{\npublic static final int *;\n}\n-keepclassmembers enum * {\n    public static **[] values();\n    public static ** valueOf(java.lang.String);\n}\n\n## UmengPush\n-dontwarn com.taobao.**\n-dontwarn anet.channel.**\n-dontwarn anetwork.channel.**\n-dontwarn org.android.**\n-dontwarn org.apache.thrift.**\n-dontwarn com.xiaomi.**\n-dontwarn com.huawei.**\n-keepattributes *Annotation*\n-keep class com.taobao.** {*;}\n-keep class org.android.** {*;}\n-keep class anet.channel.** {*;}\n-keep class com.umeng.** {*;}\n-keep class com.xiaomi.** {*;}\n-keep class com.huawei.** {*;}\n-keep class org.apache.thrift.** {*;}\n-keep class com.alibaba.sdk.android.**{*;}\n-keep class com.ut.**{*;}\n-keep class com.ta.**{*;}\n-keep public class **.R$*{\n   public static final int *;\n}\n\n#（可选）避免Log打印输出\n#-assumenosideeffects class android.util.Log {\n#   public static *** v(...);\n#   public static *** d(...);\n#   public static *** i(...);\n#   public static *** w(...);\n# }\n\n\n\n\n\n# rx\n-dontwarn javax.annotation.**\n-dontwarn javax.inject.**\n# OkHttp3\n-dontwarn okhttp3.logging.**\n-keep class okhttp3.internal.**{*;}\n-dontwarn okio.**\n# Retrofit\n-dontwarn retrofit2.**\n-keep class retrofit2.** {*;}\n-keepattributes Signature\n-keepattributes Exceptions\n\n# RxJava RxAndroid\n-dontwarn sun.misc.**\n-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {\n    long producerIndex;\n    long consumerIndex;\n}\n-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {\n    rx.internal.util.atomic.LinkedQueueNode producerNode;\n}\n-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {\n    rx.internal.util.atomic.LinkedQueueNode consumerNode;\n}\n\n\n\n\n\n\n\n\n\n\n#################################################其它第三方########################\n"
  },
  {
    "path": "app/src/androidTest/java/wgyscsf/financialcustomerview/ExampleInstrumentedTest.java",
    "content": "package com.tophold.example;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumentation test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() throws Exception {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"com.tophold.example\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"com.tophold.example\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n\n    <application\n        android:name=\".MyApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"${app_names}\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\"\n        tools:ignore=\"GoogleAppIndexingWarning\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity android:name=\".demo.fund.FundActivity\" />\n        <activity android:name=\".demo.kview.beginner.ui.KViewVerticalActivity\" />\n        <activity\n            android:name=\".demo.kview.beginner.ui.KViewHorizontalActivityActivity\"\n            android:screenOrientation=\"landscape\"\n            android:theme=\"@style/AppTheme_Fullscreen\" />\n        <activity android:name=\".demo.kview.forex.ui.ForexListActivity\" />\n        <activity android:name=\".demo.kview.forex.ui.ForexActivity\" />\n        <activity android:name=\".demo.kview.btc.ui.HuobiListActivity\" />\n        <activity android:name=\".demo.kview.btc.ui.HuobiActivity\" />\n        <activity android:name=\".demo.pie.PieChartActivity\" />\n\n        <!-- <intent-filter> -->\n        <!-- <action android:name=\"android.intent.action.MAIN\"/> -->\n\n\n        <!-- <category android:name=\"android.intent.category.LAUNCHER\"/> -->\n        <!-- </intent-filter> -->\n        <activity android:name=\".demo.seekbar.DoubleThumbSeekBarActivity\" />\n        <activity android:name=\".demo.kview.KViewActivity\"></activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/assets/fund.json",
    "content": "[\n  {\n    \"actual\": \"103\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"102\",\n    \"historyId\": 449366,\n    \"previous\": \"103\",\n    \"revised\": \"\",\n    \"timestamp\": 1456213500\n  },\n  {\n    \"actual\": \"102\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"103\",\n    \"historyId\": 449367,\n    \"previous\": \"103\",\n    \"revised\": \"101\",\n    \"timestamp\": 1458805500\n  },\n  {\n    \"actual\": \"105\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"101\",\n    \"historyId\": 449368,\n    \"previous\": \"102\",\n    \"revised\": \"104\",\n    \"timestamp\": 1461221100\n  },\n  {\n    \"actual\": \"104\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"104\",\n    \"historyId\": 449369,\n    \"previous\": \"105\",\n    \"revised\": \"\",\n    \"timestamp\": 1464072300\n  },\n  {\n    \"actual\": \"102\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"103\",\n    \"historyId\": 449370,\n    \"previous\": \"104\",\n    \"revised\": \"\",\n    \"timestamp\": 1466664300\n  },\n  {\n    \"actual\": \"103\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"101\",\n    \"historyId\": 449371,\n    \"previous\": \"102\",\n    \"revised\": \"\",\n    \"timestamp\": 1469083500\n  },\n  {\n    \"actual\": \"101\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"103\",\n    \"historyId\": 449372,\n    \"previous\": \"103\",\n    \"revised\": \"\",\n    \"timestamp\": 1472107500\n  },\n  {\n    \"actual\": \"103\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"101\",\n    \"historyId\": 449373,\n    \"previous\": \"101\",\n    \"revised\": \"\",\n    \"timestamp\": 1474526700\n  },\n  {\n    \"actual\": \"103\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"103\",\n    \"historyId\": 449374,\n    \"previous\": \"103\",\n    \"revised\": \"102\",\n    \"timestamp\": 1477377900\n  },\n  {\n    \"actual\": \"102\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"102\",\n    \"historyId\": 449375,\n    \"previous\": \"103\",\n    \"revised\": \"103\",\n    \"timestamp\": 1479973500\n  },\n  {\n    \"actual\": \"106\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"103\",\n    \"historyId\": 449376,\n    \"previous\": \"102\",\n    \"revised\": \"\",\n    \"timestamp\": 1481874300\n  },\n  {\n    \"actual\": \"106\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"106\",\n    \"historyId\": 449377,\n    \"previous\": \"106\",\n    \"revised\": \"\",\n    \"timestamp\": 1485330300\n  },\n  {\n    \"actual\": \"107\",\n    \"createTime\": \"Apr 10, 2017 12:04:14 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"106\",\n    \"historyId\": 449378,\n    \"previous\": \"106\",\n    \"revised\": \"\",\n    \"timestamp\": 1487835900\n  },\n  {\n    \"actual\": \"105\",\n    \"createTime\": \"Aug 8, 2017 12:35:07 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"107\",\n    \"historyId\": 692633,\n    \"previous\": \"107\",\n    \"revised\": \"104\",\n    \"timestamp\": 1490255100\n  },\n  {\n    \"actual\": \"108\",\n    \"createTime\": \"Aug 8, 2017 12:35:07 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"104\",\n    \"historyId\": 692634,\n    \"previous\": \"105\",\n    \"revised\": \"104\",\n    \"timestamp\": 1493102700\n  },\n  {\n    \"actual\": \"109\",\n    \"createTime\": \"Aug 8, 2017 12:35:07 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"108\",\n    \"historyId\": 692635,\n    \"previous\": \"109\",\n    \"revised\": \"\",\n    \"timestamp\": 1495521900\n  },\n  {\n    \"actual\": \"109\",\n    \"createTime\": \"Aug 8, 2017 12:35:07 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"109\",\n    \"historyId\": 692636,\n    \"previous\": \"109\",\n    \"revised\": \"108\",\n    \"timestamp\": 1498113900\n  },\n  {\n    \"actual\": \"109\",\n    \"createTime\": \"Aug 8, 2017 12:35:07 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"108\",\n    \"historyId\": 692637,\n    \"previous\": \"109\",\n    \"revised\": \"108\",\n    \"timestamp\": 1500965100\n  },\n  {\n    \"actual\": \"111\",\n    \"createTime\": \"Aug 24, 2017 6:14:38 PM\",\n    \"economicId\": 518,\n    \"forecast\": \"108\",\n    \"historyId\": 696718,\n    \"previous\": \"108\",\n    \"revised\": \"109\",\n    \"timestamp\": 1503557100\n  },\n  {\n    \"actual\": \"110\",\n    \"createTime\": \"Oct 9, 2017 9:07:19 AM\",\n    \"economicId\": 518,\n    \"forecast\": \"\",\n    \"historyId\": 698671,\n    \"previous\": \"111\",\n    \"revised\": \"\",\n    \"timestamp\": 1506408300\n  }\n]"
  },
  {
    "path": "app/src/main/assets/timesharing0.json",
    "content": "[\n  {\n    \"c\": \"148.942\",\n    \"h\": \"148.9445\",\n    \"l\": \"148.9245\",\n    \"o\": \"148.926\",\n    \"t\": \"Nov 20, 2017 2:45:00 AM\"\n  },\n  {\n    \"c\": \"148.9105\",\n    \"h\": \"148.9445\",\n    \"l\": \"148.9075\",\n    \"o\": \"148.942\",\n    \"t\": \"Nov 20, 2017 2:46:00 AM\"\n  },\n  {\n    \"c\": \"148.9175\",\n    \"h\": \"148.9175\",\n    \"l\": \"148.878\",\n    \"o\": \"148.906\",\n    \"t\": \"Nov 20, 2017 2:47:00 AM\"\n  },\n  {\n    \"c\": \"148.9155\",\n    \"h\": \"148.933\",\n    \"l\": \"148.905\",\n    \"o\": \"148.9175\",\n    \"t\": \"Nov 20, 2017 2:48:00 AM\"\n  },\n  {\n    \"c\": \"148.9035\",\n    \"h\": \"148.9195\",\n    \"l\": \"148.8955\",\n    \"o\": \"148.916\",\n    \"t\": \"Nov 20, 2017 2:49:00 AM\"\n  },\n  {\n    \"c\": \"148.9045\",\n    \"h\": \"148.9075\",\n    \"l\": \"148.8975\",\n    \"o\": \"148.9035\",\n    \"t\": \"Nov 20, 2017 2:50:00 AM\"\n  },\n  {\n    \"c\": \"148.9\",\n    \"h\": \"148.9045\",\n    \"l\": \"148.9\",\n    \"o\": \"148.9045\",\n    \"t\": \"Nov 20, 2017 2:51:00 AM\"\n  },\n  {\n    \"c\": \"148.9025\",\n    \"h\": \"148.908\",\n    \"l\": \"148.8915\",\n    \"o\": \"148.9005\",\n    \"t\": \"Nov 20, 2017 2:52:00 AM\"\n  },\n  {\n    \"c\": \"148.926\",\n    \"h\": \"148.926\",\n    \"l\": \"148.9015\",\n    \"o\": \"148.9015\",\n    \"t\": \"Nov 20, 2017 2:53:00 AM\"\n  },\n  {\n    \"c\": \"148.9105\",\n    \"h\": \"148.926\",\n    \"l\": \"148.91\",\n    \"o\": \"148.926\",\n    \"t\": \"Nov 20, 2017 2:54:00 AM\"\n  },\n  {\n    \"c\": \"148.9265\",\n    \"h\": \"148.941\",\n    \"l\": \"148.91\",\n    \"o\": \"148.91\",\n    \"t\": \"Nov 20, 2017 2:55:00 AM\"\n  },\n  {\n    \"c\": \"148.933\",\n    \"h\": \"148.9455\",\n    \"l\": \"148.9255\",\n    \"o\": \"148.9265\",\n    \"t\": \"Nov 20, 2017 2:56:00 AM\"\n  },\n  {\n    \"c\": \"148.94\",\n    \"h\": \"148.952\",\n    \"l\": \"148.932\",\n    \"o\": \"148.9325\",\n    \"t\": \"Nov 20, 2017 2:57:00 AM\"\n  },\n  {\n    \"c\": \"148.9325\",\n    \"h\": \"148.9465\",\n    \"l\": \"148.928\",\n    \"o\": \"148.94\",\n    \"t\": \"Nov 20, 2017 2:58:00 AM\"\n  },\n  {\n    \"c\": \"148.937\",\n    \"h\": \"148.9395\",\n    \"l\": \"148.913\",\n    \"o\": \"148.932\",\n    \"t\": \"Nov 20, 2017 2:59:00 AM\"\n  },\n  {\n    \"c\": \"148.9635\",\n    \"h\": \"148.9655\",\n    \"l\": \"148.937\",\n    \"o\": \"148.937\",\n    \"t\": \"Nov 20, 2017 3:00:00 AM\"\n  },\n  {\n    \"c\": \"148.973\",\n    \"h\": \"148.978\",\n    \"l\": \"148.962\",\n    \"o\": \"148.962\",\n    \"t\": \"Nov 20, 2017 3:01:00 AM\"\n  },\n  {\n    \"c\": \"148.9725\",\n    \"h\": \"148.976\",\n    \"l\": \"148.966\",\n    \"o\": \"148.9725\",\n    \"t\": \"Nov 20, 2017 3:02:00 AM\"\n  },\n  {\n    \"c\": \"148.975\",\n    \"h\": \"148.975\",\n    \"l\": \"148.965\",\n    \"o\": \"148.9725\",\n    \"t\": \"Nov 20, 2017 3:03:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.03\",\n    \"l\": \"148.9635\",\n    \"o\": \"148.976\",\n    \"t\": \"Nov 20, 2017 3:04:00 AM\"\n  },\n  {\n    \"c\": \"148.972\",\n    \"h\": \"149.093\",\n    \"l\": \"148.9695\",\n    \"o\": \"149.024\",\n    \"t\": \"Nov 20, 2017 3:05:00 AM\"\n  },\n  {\n    \"c\": \"148.981\",\n    \"h\": \"148.981\",\n    \"l\": \"148.9615\",\n    \"o\": \"148.973\",\n    \"t\": \"Nov 20, 2017 3:06:00 AM\"\n  },\n  {\n    \"c\": \"148.9825\",\n    \"h\": \"148.9885\",\n    \"l\": \"148.9755\",\n    \"o\": \"148.981\",\n    \"t\": \"Nov 20, 2017 3:07:00 AM\"\n  },\n  {\n    \"c\": \"148.9695\",\n    \"h\": \"148.994\",\n    \"l\": \"148.9665\",\n    \"o\": \"148.982\",\n    \"t\": \"Nov 20, 2017 3:08:00 AM\"\n  },\n  {\n    \"c\": \"148.9675\",\n    \"h\": \"148.9815\",\n    \"l\": \"148.9635\",\n    \"o\": \"148.97\",\n    \"t\": \"Nov 20, 2017 3:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0195\",\n    \"h\": \"149.0215\",\n    \"l\": \"148.963\",\n    \"o\": \"148.9675\",\n    \"t\": \"Nov 20, 2017 3:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.0355\",\n    \"l\": \"149.005\",\n    \"o\": \"149.0185\",\n    \"t\": \"Nov 20, 2017 3:11:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.036\",\n    \"t\": \"Nov 20, 2017 3:12:00 AM\"\n  },\n  {\n    \"c\": \"149.02\",\n    \"h\": \"149.0315\",\n    \"l\": \"149.016\",\n    \"o\": \"149.0295\",\n    \"t\": \"Nov 20, 2017 3:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.071\",\n    \"l\": \"149.0195\",\n    \"o\": \"149.0215\",\n    \"t\": \"Nov 20, 2017 3:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0655\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.032\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 20, 2017 3:15:00 AM\"\n  },\n  {\n    \"c\": \"149.065\",\n    \"h\": \"149.0795\",\n    \"l\": \"149.059\",\n    \"o\": \"149.0655\",\n    \"t\": \"Nov 20, 2017 3:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.09\",\n    \"l\": \"149.062\",\n    \"o\": \"149.0645\",\n    \"t\": \"Nov 20, 2017 3:17:00 AM\"\n  },\n  {\n    \"c\": \"149.078\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.06\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 20, 2017 3:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.086\",\n    \"l\": \"149.0755\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 20, 2017 3:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1755\",\n    \"l\": \"149.085\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 20, 2017 3:20:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.178\",\n    \"l\": \"149.103\",\n    \"o\": \"149.1735\",\n    \"t\": \"Nov 20, 2017 3:21:00 AM\"\n  },\n  {\n    \"c\": \"149.1395\",\n    \"h\": \"149.149\",\n    \"l\": \"149.1255\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 20, 2017 3:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1385\",\n    \"t\": \"Nov 20, 2017 3:23:00 AM\"\n  },\n  {\n    \"c\": \"149.157\",\n    \"h\": \"149.1615\",\n    \"l\": \"149.1475\",\n    \"o\": \"149.1595\",\n    \"t\": \"Nov 20, 2017 3:24:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.158\",\n    \"l\": \"149.131\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 20, 2017 3:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.157\",\n    \"l\": \"149.145\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 20, 2017 3:26:00 AM\"\n  },\n  {\n    \"c\": \"149.165\",\n    \"h\": \"149.171\",\n    \"l\": \"149.1475\",\n    \"o\": \"149.1485\",\n    \"t\": \"Nov 20, 2017 3:27:00 AM\"\n  },\n  {\n    \"c\": \"149.178\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1635\",\n    \"t\": \"Nov 20, 2017 3:28:00 AM\"\n  },\n  {\n    \"c\": \"149.19\",\n    \"h\": \"149.19\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.178\",\n    \"t\": \"Nov 20, 2017 3:29:00 AM\"\n  },\n  {\n    \"c\": \"149.1835\",\n    \"h\": \"149.198\",\n    \"l\": \"149.177\",\n    \"o\": \"149.191\",\n    \"t\": \"Nov 20, 2017 3:30:00 AM\"\n  },\n  {\n    \"c\": \"149.177\",\n    \"h\": \"149.187\",\n    \"l\": \"149.167\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 20, 2017 3:31:00 AM\"\n  },\n  {\n    \"c\": \"149.1725\",\n    \"h\": \"149.1855\",\n    \"l\": \"149.1685\",\n    \"o\": \"149.1775\",\n    \"t\": \"Nov 20, 2017 3:32:00 AM\"\n  },\n  {\n    \"c\": \"149.193\",\n    \"h\": \"149.195\",\n    \"l\": \"149.168\",\n    \"o\": \"149.1725\",\n    \"t\": \"Nov 20, 2017 3:33:00 AM\"\n  },\n  {\n    \"c\": \"149.191\",\n    \"h\": \"149.204\",\n    \"l\": \"149.1825\",\n    \"o\": \"149.1935\",\n    \"t\": \"Nov 20, 2017 3:34:00 AM\"\n  },\n  {\n    \"c\": \"149.195\",\n    \"h\": \"149.198\",\n    \"l\": \"149.1825\",\n    \"o\": \"149.1905\",\n    \"t\": \"Nov 20, 2017 3:35:00 AM\"\n  },\n  {\n    \"c\": \"149.197\",\n    \"h\": \"149.2395\",\n    \"l\": \"149.193\",\n    \"o\": \"149.196\",\n    \"t\": \"Nov 20, 2017 3:36:00 AM\"\n  },\n  {\n    \"c\": \"149.2235\",\n    \"h\": \"149.232\",\n    \"l\": \"149.193\",\n    \"o\": \"149.197\",\n    \"t\": \"Nov 20, 2017 3:37:00 AM\"\n  },\n  {\n    \"c\": \"149.2065\",\n    \"h\": \"149.2355\",\n    \"l\": \"149.2065\",\n    \"o\": \"149.224\",\n    \"t\": \"Nov 20, 2017 3:38:00 AM\"\n  },\n  {\n    \"c\": \"149.2145\",\n    \"h\": \"149.2185\",\n    \"l\": \"149.2075\",\n    \"o\": \"149.2075\",\n    \"t\": \"Nov 20, 2017 3:39:00 AM\"\n  },\n  {\n    \"c\": \"149.2075\",\n    \"h\": \"149.2145\",\n    \"l\": \"149.2045\",\n    \"o\": \"149.2145\",\n    \"t\": \"Nov 20, 2017 3:40:00 AM\"\n  },\n  {\n    \"c\": \"149.1765\",\n    \"h\": \"149.2125\",\n    \"l\": \"149.1765\",\n    \"o\": \"149.2085\",\n    \"t\": \"Nov 20, 2017 3:41:00 AM\"\n  },\n  {\n    \"c\": \"149.171\",\n    \"h\": \"149.189\",\n    \"l\": \"149.1655\",\n    \"o\": \"149.1775\",\n    \"t\": \"Nov 20, 2017 3:42:00 AM\"\n  },\n  {\n    \"c\": \"149.183\",\n    \"h\": \"149.188\",\n    \"l\": \"149.165\",\n    \"o\": \"149.171\",\n    \"t\": \"Nov 20, 2017 3:43:00 AM\"\n  },\n  {\n    \"c\": \"149.181\",\n    \"h\": \"149.1925\",\n    \"l\": \"149.1685\",\n    \"o\": \"149.183\",\n    \"t\": \"Nov 20, 2017 3:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1775\",\n    \"h\": \"149.192\",\n    \"l\": \"149.172\",\n    \"o\": \"149.179\",\n    \"t\": \"Nov 20, 2017 3:45:00 AM\"\n  },\n  {\n    \"c\": \"149.174\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1765\",\n    \"t\": \"Nov 20, 2017 3:46:00 AM\"\n  },\n  {\n    \"c\": \"149.17\",\n    \"h\": \"149.1885\",\n    \"l\": \"149.17\",\n    \"o\": \"149.1745\",\n    \"t\": \"Nov 20, 2017 3:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.166\",\n    \"o\": \"149.1705\",\n    \"t\": \"Nov 20, 2017 3:48:00 AM\"\n  },\n  {\n    \"c\": \"149.1815\",\n    \"h\": \"149.1875\",\n    \"l\": \"149.1735\",\n    \"o\": \"149.1735\",\n    \"t\": \"Nov 20, 2017 3:49:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.181\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.1805\",\n    \"t\": \"Nov 20, 2017 3:50:00 AM\"\n  },\n  {\n    \"c\": \"149.1465\",\n    \"h\": \"149.162\",\n    \"l\": \"149.1455\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 20, 2017 3:51:00 AM\"\n  },\n  {\n    \"c\": \"149.1545\",\n    \"h\": \"149.1625\",\n    \"l\": \"149.141\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 20, 2017 3:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1405\",\n    \"h\": \"149.163\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1545\",\n    \"t\": \"Nov 20, 2017 3:53:00 AM\"\n  },\n  {\n    \"c\": \"149.148\",\n    \"h\": \"149.1505\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1405\",\n    \"t\": \"Nov 20, 2017 3:54:00 AM\"\n  },\n  {\n    \"c\": \"149.153\",\n    \"h\": \"149.156\",\n    \"l\": \"149.129\",\n    \"o\": \"149.148\",\n    \"t\": \"Nov 20, 2017 3:55:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.154\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1535\",\n    \"t\": \"Nov 20, 2017 3:56:00 AM\"\n  },\n  {\n    \"c\": \"149.163\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 20, 2017 3:57:00 AM\"\n  },\n  {\n    \"c\": \"149.166\",\n    \"h\": \"149.174\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.163\",\n    \"t\": \"Nov 20, 2017 3:58:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1435\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 20, 2017 3:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1245\",\n    \"h\": \"149.1515\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 20, 2017 4:00:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.1295\",\n    \"l\": \"149.115\",\n    \"o\": \"149.1245\",\n    \"t\": \"Nov 20, 2017 4:01:00 AM\"\n  },\n  {\n    \"c\": \"149.119\",\n    \"h\": \"149.125\",\n    \"l\": \"149.1145\",\n    \"o\": \"149.116\",\n    \"t\": \"Nov 20, 2017 4:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1325\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.11\",\n    \"o\": \"149.1185\",\n    \"t\": \"Nov 20, 2017 4:03:00 AM\"\n  },\n  {\n    \"c\": \"149.152\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1325\",\n    \"o\": \"149.1325\",\n    \"t\": \"Nov 20, 2017 4:04:00 AM\"\n  },\n  {\n    \"c\": \"149.161\",\n    \"h\": \"149.164\",\n    \"l\": \"149.152\",\n    \"o\": \"149.152\",\n    \"t\": \"Nov 20, 2017 4:05:00 AM\"\n  },\n  {\n    \"c\": \"149.1595\",\n    \"h\": \"149.169\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1615\",\n    \"t\": \"Nov 20, 2017 4:06:00 AM\"\n  },\n  {\n    \"c\": \"149.1475\",\n    \"h\": \"149.166\",\n    \"l\": \"149.144\",\n    \"o\": \"149.1595\",\n    \"t\": \"Nov 20, 2017 4:07:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.152\",\n    \"l\": \"149.137\",\n    \"o\": \"149.148\",\n    \"t\": \"Nov 20, 2017 4:08:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.1485\",\n    \"l\": \"149.1345\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 20, 2017 4:09:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.144\",\n    \"l\": \"149.1265\",\n    \"o\": \"149.137\",\n    \"t\": \"Nov 20, 2017 4:10:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.152\",\n    \"l\": \"149.1365\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 20, 2017 4:11:00 AM\"\n  },\n  {\n    \"c\": \"149.1355\",\n    \"h\": \"149.1475\",\n    \"l\": \"149.133\",\n    \"o\": \"149.1475\",\n    \"t\": \"Nov 20, 2017 4:12:00 AM\"\n  },\n  {\n    \"c\": \"149.116\",\n    \"h\": \"149.138\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1355\",\n    \"t\": \"Nov 20, 2017 4:13:00 AM\"\n  },\n  {\n    \"c\": \"149.13\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1165\",\n    \"t\": \"Nov 20, 2017 4:14:00 AM\"\n  },\n  {\n    \"c\": \"149.124\",\n    \"h\": \"149.13\",\n    \"l\": \"149.1195\",\n    \"o\": \"149.1295\",\n    \"t\": \"Nov 20, 2017 4:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1265\",\n    \"h\": \"149.1285\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.1245\",\n    \"t\": \"Nov 20, 2017 4:16:00 AM\"\n  },\n  {\n    \"c\": \"149.123\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.112\",\n    \"o\": \"149.128\",\n    \"t\": \"Nov 20, 2017 4:17:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.126\",\n    \"l\": \"149.109\",\n    \"o\": \"149.1225\",\n    \"t\": \"Nov 20, 2017 4:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1125\",\n    \"h\": \"149.123\",\n    \"l\": \"149.11\",\n    \"o\": \"149.1145\",\n    \"t\": \"Nov 20, 2017 4:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.117\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.112\",\n    \"t\": \"Nov 20, 2017 4:20:00 AM\"\n  },\n  {\n    \"c\": \"149.106\",\n    \"h\": \"149.115\",\n    \"l\": \"149.1045\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 20, 2017 4:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.105\",\n    \"l\": \"149.094\",\n    \"o\": \"149.1045\",\n    \"t\": \"Nov 20, 2017 4:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1195\",\n    \"h\": \"149.1195\",\n    \"l\": \"149.095\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 20, 2017 4:23:00 AM\"\n  },\n  {\n    \"c\": \"149.123\",\n    \"h\": \"149.1305\",\n    \"l\": \"149.115\",\n    \"o\": \"149.119\",\n    \"t\": \"Nov 20, 2017 4:24:00 AM\"\n  },\n  {\n    \"c\": \"149.134\",\n    \"h\": \"149.1355\",\n    \"l\": \"149.1215\",\n    \"o\": \"149.122\",\n    \"t\": \"Nov 20, 2017 4:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1215\",\n    \"h\": \"149.137\",\n    \"l\": \"149.12\",\n    \"o\": \"149.134\",\n    \"t\": \"Nov 20, 2017 4:26:00 AM\"\n  },\n  {\n    \"c\": \"149.1335\",\n    \"h\": \"149.137\",\n    \"l\": \"149.118\",\n    \"o\": \"149.1205\",\n    \"t\": \"Nov 20, 2017 4:27:00 AM\"\n  },\n  {\n    \"c\": \"149.144\",\n    \"h\": \"149.1525\",\n    \"l\": \"149.134\",\n    \"o\": \"149.134\",\n    \"t\": \"Nov 20, 2017 4:28:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.1585\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.1445\",\n    \"t\": \"Nov 20, 2017 4:29:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.151\",\n    \"l\": \"149.136\",\n    \"o\": \"149.1435\",\n    \"t\": \"Nov 20, 2017 4:30:00 AM\"\n  },\n  {\n    \"c\": \"149.114\",\n    \"h\": \"149.147\",\n    \"l\": \"149.114\",\n    \"o\": \"149.146\",\n    \"t\": \"Nov 20, 2017 4:31:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.1025\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 20, 2017 4:32:00 AM\"\n  },\n  {\n    \"c\": \"149.0985\",\n    \"h\": \"149.1115\",\n    \"l\": \"149.096\",\n    \"o\": \"149.1035\",\n    \"t\": \"Nov 20, 2017 4:33:00 AM\"\n  },\n  {\n    \"c\": \"149.0995\",\n    \"h\": \"149.1005\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 20, 2017 4:34:00 AM\"\n  },\n  {\n    \"c\": \"149.088\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 20, 2017 4:35:00 AM\"\n  },\n  {\n    \"c\": \"149.089\",\n    \"h\": \"149.089\",\n    \"l\": \"149.082\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 20, 2017 4:36:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.095\",\n    \"l\": \"149.0815\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 20, 2017 4:37:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 20, 2017 4:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0945\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.09\",\n    \"t\": \"Nov 20, 2017 4:39:00 AM\"\n  },\n  {\n    \"c\": \"149.098\",\n    \"h\": \"149.099\",\n    \"l\": \"149.0835\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 20, 2017 4:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0815\",\n    \"h\": \"149.0995\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.098\",\n    \"t\": \"Nov 20, 2017 4:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0875\",\n    \"h\": \"149.092\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 20, 2017 4:42:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 20, 2017 4:43:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.079\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 20, 2017 4:44:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.0795\",\n    \"t\": \"Nov 20, 2017 4:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.0715\",\n    \"o\": \"149.075\",\n    \"t\": \"Nov 20, 2017 4:46:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.079\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 20, 2017 4:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0835\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.077\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 20, 2017 4:48:00 AM\"\n  },\n  {\n    \"c\": \"149.0765\",\n    \"h\": \"149.083\",\n    \"l\": \"149.073\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 20, 2017 4:49:00 AM\"\n  },\n  {\n    \"c\": \"149.069\",\n    \"h\": \"149.078\",\n    \"l\": \"149.0665\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 20, 2017 4:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.076\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.07\",\n    \"t\": \"Nov 20, 2017 4:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0735\",\n    \"h\": \"149.076\",\n    \"l\": \"149.064\",\n    \"o\": \"149.0725\",\n    \"t\": \"Nov 20, 2017 4:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0675\",\n    \"h\": \"149.0735\",\n    \"l\": \"149.063\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 20, 2017 4:53:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.083\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.067\",\n    \"t\": \"Nov 20, 2017 4:54:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0645\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 20, 2017 4:55:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.0795\",\n    \"l\": \"149.061\",\n    \"o\": \"149.0785\",\n    \"t\": \"Nov 20, 2017 4:56:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.0655\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 20, 2017 4:57:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 20, 2017 4:58:00 AM\"\n  },\n  {\n    \"c\": \"149.031\",\n    \"h\": \"149.0545\",\n    \"l\": \"149.025\",\n    \"o\": \"149.043\",\n    \"t\": \"Nov 20, 2017 4:59:00 AM\"\n  },\n  {\n    \"c\": \"149.0095\",\n    \"h\": \"149.0455\",\n    \"l\": \"149.002\",\n    \"o\": \"149.0305\",\n    \"t\": \"Nov 20, 2017 5:00:00 AM\"\n  },\n  {\n    \"c\": \"149.007\",\n    \"h\": \"149.015\",\n    \"l\": \"149.0\",\n    \"o\": \"149.01\",\n    \"t\": \"Nov 20, 2017 5:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0045\",\n    \"h\": \"149.0095\",\n    \"l\": \"149.0\",\n    \"o\": \"149.008\",\n    \"t\": \"Nov 20, 2017 5:02:00 AM\"\n  },\n  {\n    \"c\": \"148.997\",\n    \"h\": \"149.0035\",\n    \"l\": \"148.9915\",\n    \"o\": \"149.0035\",\n    \"t\": \"Nov 20, 2017 5:03:00 AM\"\n  },\n  {\n    \"c\": \"148.989\",\n    \"h\": \"148.998\",\n    \"l\": \"148.985\",\n    \"o\": \"148.997\",\n    \"t\": \"Nov 20, 2017 5:04:00 AM\"\n  },\n  {\n    \"c\": \"148.9855\",\n    \"h\": \"149.0\",\n    \"l\": \"148.9825\",\n    \"o\": \"148.99\",\n    \"t\": \"Nov 20, 2017 5:05:00 AM\"\n  },\n  {\n    \"c\": \"148.977\",\n    \"h\": \"148.9935\",\n    \"l\": \"148.974\",\n    \"o\": \"148.986\",\n    \"t\": \"Nov 20, 2017 5:06:00 AM\"\n  },\n  {\n    \"c\": \"148.97\",\n    \"h\": \"148.9815\",\n    \"l\": \"148.961\",\n    \"o\": \"148.9765\",\n    \"t\": \"Nov 20, 2017 5:07:00 AM\"\n  },\n  {\n    \"c\": \"148.9865\",\n    \"h\": \"148.988\",\n    \"l\": \"148.9675\",\n    \"o\": \"148.9695\",\n    \"t\": \"Nov 20, 2017 5:08:00 AM\"\n  },\n  {\n    \"c\": \"149.002\",\n    \"h\": \"149.002\",\n    \"l\": \"148.9855\",\n    \"o\": \"148.9865\",\n    \"t\": \"Nov 20, 2017 5:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0085\",\n    \"h\": \"149.014\",\n    \"l\": \"148.9905\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 20, 2017 5:10:00 AM\"\n  },\n  {\n    \"c\": \"149.007\",\n    \"h\": \"149.0085\",\n    \"l\": \"148.9965\",\n    \"o\": \"149.0075\",\n    \"t\": \"Nov 20, 2017 5:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0185\",\n    \"h\": \"149.0185\",\n    \"l\": \"149.007\",\n    \"o\": \"149.007\",\n    \"t\": \"Nov 20, 2017 5:12:00 AM\"\n  },\n  {\n    \"c\": \"149.0165\",\n    \"h\": \"149.0215\",\n    \"l\": \"149.0135\",\n    \"o\": \"149.0185\",\n    \"t\": \"Nov 20, 2017 5:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0305\",\n    \"h\": \"149.033\",\n    \"l\": \"149.0145\",\n    \"o\": \"149.0175\",\n    \"t\": \"Nov 20, 2017 5:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0365\",\n    \"h\": \"149.0375\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.03\",\n    \"t\": \"Nov 20, 2017 5:15:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.04\",\n    \"l\": \"149.033\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 20, 2017 5:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.047\",\n    \"l\": \"149.0375\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 20, 2017 5:17:00 AM\"\n  },\n  {\n    \"c\": \"149.0455\",\n    \"h\": \"149.051\",\n    \"l\": \"149.038\",\n    \"o\": \"149.0405\",\n    \"t\": \"Nov 20, 2017 5:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0535\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0455\",\n    \"o\": \"149.0455\",\n    \"t\": \"Nov 20, 2017 5:19:00 AM\"\n  },\n  {\n    \"c\": \"149.055\",\n    \"h\": \"149.059\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 20, 2017 5:20:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.0455\",\n    \"o\": \"149.055\",\n    \"t\": \"Nov 20, 2017 5:21:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0495\",\n    \"o\": \"149.0635\",\n    \"t\": \"Nov 20, 2017 5:22:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.051\",\n    \"t\": \"Nov 20, 2017 5:23:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0645\",\n    \"l\": \"149.046\",\n    \"o\": \"149.0645\",\n    \"t\": \"Nov 20, 2017 5:24:00 AM\"\n  },\n  {\n    \"c\": \"149.0645\",\n    \"h\": \"149.0645\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.056\",\n    \"t\": \"Nov 20, 2017 5:25:00 AM\"\n  },\n  {\n    \"c\": \"149.076\",\n    \"h\": \"149.077\",\n    \"l\": \"149.063\",\n    \"o\": \"149.063\",\n    \"t\": \"Nov 20, 2017 5:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0805\",\n    \"l\": \"149.0725\",\n    \"o\": \"149.0755\",\n    \"t\": \"Nov 20, 2017 5:27:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.087\",\n    \"l\": \"149.08\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 20, 2017 5:28:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.084\",\n    \"t\": \"Nov 20, 2017 5:29:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 20, 2017 5:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0975\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 20, 2017 5:31:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.1015\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 20, 2017 5:32:00 AM\"\n  },\n  {\n    \"c\": \"149.107\",\n    \"h\": \"149.1095\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.0835\",\n    \"t\": \"Nov 20, 2017 5:33:00 AM\"\n  },\n  {\n    \"c\": \"149.1025\",\n    \"h\": \"149.113\",\n    \"l\": \"149.095\",\n    \"o\": \"149.1055\",\n    \"t\": \"Nov 20, 2017 5:34:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.1035\",\n    \"l\": \"149.0935\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 20, 2017 5:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.097\",\n    \"l\": \"149.091\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 20, 2017 5:36:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0835\",\n    \"o\": \"149.0925\",\n    \"t\": \"Nov 20, 2017 5:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0755\",\n    \"h\": \"149.087\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 20, 2017 5:38:00 AM\"\n  },\n  {\n    \"c\": \"149.05\",\n    \"h\": \"149.078\",\n    \"l\": \"149.0495\",\n    \"o\": \"149.0765\",\n    \"t\": \"Nov 20, 2017 5:39:00 AM\"\n  },\n  {\n    \"c\": \"149.018\",\n    \"h\": \"149.051\",\n    \"l\": \"149.0155\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 20, 2017 5:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0365\",\n    \"h\": \"149.037\",\n    \"l\": \"149.0175\",\n    \"o\": \"149.018\",\n    \"t\": \"Nov 20, 2017 5:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.0375\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 20, 2017 5:42:00 AM\"\n  },\n  {\n    \"c\": \"149.057\",\n    \"h\": \"149.07\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 20, 2017 5:43:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0575\",\n    \"t\": \"Nov 20, 2017 5:44:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.074\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.0655\",\n    \"t\": \"Nov 20, 2017 5:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.084\",\n    \"l\": \"149.0725\",\n    \"o\": \"149.0735\",\n    \"t\": \"Nov 20, 2017 5:46:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.08\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 20, 2017 5:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0685\",\n    \"h\": \"149.0775\",\n    \"l\": \"149.068\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 20, 2017 5:48:00 AM\"\n  },\n  {\n    \"c\": \"149.067\",\n    \"h\": \"149.0685\",\n    \"l\": \"149.066\",\n    \"o\": \"149.067\",\n    \"t\": \"Nov 20, 2017 5:49:00 AM\"\n  },\n  {\n    \"c\": \"149.045\",\n    \"h\": \"149.073\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.066\",\n    \"t\": \"Nov 20, 2017 5:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.046\",\n    \"l\": \"149.0225\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 20, 2017 5:51:00 AM\"\n  },\n  {\n    \"c\": \"149.004\",\n    \"h\": \"149.023\",\n    \"l\": \"149.004\",\n    \"o\": \"149.023\",\n    \"t\": \"Nov 20, 2017 5:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0175\",\n    \"h\": \"149.022\",\n    \"l\": \"149.0045\",\n    \"o\": \"149.0045\",\n    \"t\": \"Nov 20, 2017 5:53:00 AM\"\n  },\n  {\n    \"c\": \"149.011\",\n    \"h\": \"149.0195\",\n    \"l\": \"149.008\",\n    \"o\": \"149.0175\",\n    \"t\": \"Nov 20, 2017 5:54:00 AM\"\n  },\n  {\n    \"c\": \"149.009\",\n    \"h\": \"149.0115\",\n    \"l\": \"149.001\",\n    \"o\": \"149.0115\",\n    \"t\": \"Nov 20, 2017 5:55:00 AM\"\n  },\n  {\n    \"c\": \"149.001\",\n    \"h\": \"149.0155\",\n    \"l\": \"148.9975\",\n    \"o\": \"149.007\",\n    \"t\": \"Nov 20, 2017 5:56:00 AM\"\n  },\n  {\n    \"c\": \"149.0025\",\n    \"h\": \"149.005\",\n    \"l\": \"148.998\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 20, 2017 5:57:00 AM\"\n  },\n  {\n    \"c\": \"149.041\",\n    \"h\": \"149.0555\",\n    \"l\": \"149.0025\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 20, 2017 5:58:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.069\",\n    \"l\": \"149.033\",\n    \"o\": \"149.042\",\n    \"t\": \"Nov 20, 2017 5:59:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.0805\",\n    \"l\": \"149.0405\",\n    \"o\": \"149.0805\",\n    \"t\": \"Nov 20, 2017 6:00:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.039\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 20, 2017 6:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0415\",\n    \"h\": \"149.0415\",\n    \"l\": \"149.0355\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 20, 2017 6:02:00 AM\"\n  },\n  {\n    \"c\": \"149.0635\",\n    \"h\": \"149.0635\",\n    \"l\": \"149.0415\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 20, 2017 6:03:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.1045\",\n    \"l\": \"149.064\",\n    \"o\": \"149.064\",\n    \"t\": \"Nov 20, 2017 6:04:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.105\",\n    \"l\": \"149.0915\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 20, 2017 6:05:00 AM\"\n  },\n  {\n    \"c\": \"149.0815\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0925\",\n    \"t\": \"Nov 20, 2017 6:06:00 AM\"\n  },\n  {\n    \"c\": \"149.0875\",\n    \"h\": \"149.0885\",\n    \"l\": \"149.082\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 20, 2017 6:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0925\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 20, 2017 6:08:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 20, 2017 6:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.0945\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0935\",\n    \"t\": \"Nov 20, 2017 6:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.088\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 20, 2017 6:11:00 AM\"\n  },\n  {\n    \"c\": \"149.097\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0945\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 20, 2017 6:12:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0965\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 20, 2017 6:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.097\",\n    \"l\": \"149.0965\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 20, 2017 6:14:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.092\",\n    \"o\": \"149.095\",\n    \"t\": \"Nov 20, 2017 6:15:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.099\",\n    \"l\": \"149.094\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 20, 2017 6:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 20, 2017 6:17:00 AM\"\n  },\n  {\n    \"c\": \"149.1015\",\n    \"h\": \"149.102\",\n    \"l\": \"149.0885\",\n    \"o\": \"149.091\",\n    \"t\": \"Nov 20, 2017 6:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0955\",\n    \"h\": \"149.107\",\n    \"l\": \"149.0905\",\n    \"o\": \"149.1005\",\n    \"t\": \"Nov 20, 2017 6:19:00 AM\"\n  },\n  {\n    \"c\": \"149.0935\",\n    \"h\": \"149.105\",\n    \"l\": \"149.0905\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 20, 2017 6:20:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.094\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 20, 2017 6:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0925\",\n    \"h\": \"149.096\",\n    \"l\": \"149.0925\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 20, 2017 6:22:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0855\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 20, 2017 6:23:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.09\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 20, 2017 6:24:00 AM\"\n  },\n  {\n    \"c\": \"149.088\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 20, 2017 6:25:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.0875\",\n    \"l\": \"149.084\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 20, 2017 6:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.0635\",\n    \"o\": \"149.0825\",\n    \"t\": \"Nov 20, 2017 6:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.0865\",\n    \"l\": \"149.078\",\n    \"o\": \"149.0795\",\n    \"t\": \"Nov 20, 2017 6:28:00 AM\"\n  },\n  {\n    \"c\": \"149.065\",\n    \"h\": \"149.0885\",\n    \"l\": \"149.062\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 20, 2017 6:29:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.065\",\n    \"l\": \"149.052\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 20, 2017 6:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.094\",\n    \"l\": \"149.061\",\n    \"o\": \"149.0625\",\n    \"t\": \"Nov 20, 2017 6:31:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 20, 2017 6:32:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.088\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 20, 2017 6:33:00 AM\"\n  },\n  {\n    \"c\": \"149.089\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 20, 2017 6:34:00 AM\"\n  },\n  {\n    \"c\": \"149.0865\",\n    \"h\": \"149.095\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 20, 2017 6:35:00 AM\"\n  },\n  {\n    \"c\": \"149.097\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 20, 2017 6:36:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 20, 2017 6:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.095\",\n    \"l\": \"149.067\",\n    \"o\": \"149.092\",\n    \"t\": \"Nov 20, 2017 6:38:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.0815\",\n    \"l\": \"149.074\",\n    \"o\": \"149.074\",\n    \"t\": \"Nov 20, 2017 6:39:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 20, 2017 6:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0785\",\n    \"h\": \"149.08\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.077\",\n    \"t\": \"Nov 20, 2017 6:41:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 20, 2017 6:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0765\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.076\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 20, 2017 6:43:00 AM\"\n  },\n  {\n    \"c\": \"149.075\",\n    \"h\": \"149.0765\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 20, 2017 6:44:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0745\",\n    \"l\": \"149.053\",\n    \"o\": \"149.0745\",\n    \"t\": \"Nov 20, 2017 6:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0375\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0355\",\n    \"o\": \"149.0555\",\n    \"t\": \"Nov 20, 2017 6:46:00 AM\"\n  },\n  {\n    \"c\": \"149.0415\",\n    \"h\": \"149.0425\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.0395\",\n    \"t\": \"Nov 20, 2017 6:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0445\",\n    \"h\": \"149.045\",\n    \"l\": \"149.04\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 20, 2017 6:48:00 AM\"\n  },\n  {\n    \"c\": \"149.059\",\n    \"h\": \"149.06\",\n    \"l\": \"149.045\",\n    \"o\": \"149.0455\",\n    \"t\": \"Nov 20, 2017 6:49:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.059\",\n    \"l\": \"149.049\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 20, 2017 6:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.054\",\n    \"l\": \"149.05\",\n    \"o\": \"149.0515\",\n    \"t\": \"Nov 20, 2017 6:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.052\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.052\",\n    \"t\": \"Nov 20, 2017 6:52:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.0475\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 20, 2017 6:53:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.04\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 20, 2017 6:54:00 AM\"\n  },\n  {\n    \"c\": \"149.0345\",\n    \"h\": \"149.04\",\n    \"l\": \"149.034\",\n    \"o\": \"149.0385\",\n    \"t\": \"Nov 20, 2017 6:55:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.045\",\n    \"l\": \"149.034\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 20, 2017 6:56:00 AM\"\n  },\n  {\n    \"c\": \"149.0245\",\n    \"h\": \"149.0425\",\n    \"l\": \"149.022\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 20, 2017 6:57:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.037\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 20, 2017 6:58:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.0285\",\n    \"l\": \"149.015\",\n    \"o\": \"149.0285\",\n    \"t\": \"Nov 20, 2017 6:59:00 AM\"\n  },\n  {\n    \"c\": \"149.032\",\n    \"h\": \"149.033\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 20, 2017 7:00:00 AM\"\n  },\n  {\n    \"c\": \"149.025\",\n    \"h\": \"149.035\",\n    \"l\": \"149.022\",\n    \"o\": \"149.031\",\n    \"t\": \"Nov 20, 2017 7:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0245\",\n    \"h\": \"149.029\",\n    \"l\": \"149.011\",\n    \"o\": \"149.0245\",\n    \"t\": \"Nov 20, 2017 7:02:00 AM\"\n  },\n  {\n    \"c\": \"149.019\",\n    \"h\": \"149.029\",\n    \"l\": \"149.0135\",\n    \"o\": \"149.026\",\n    \"t\": \"Nov 20, 2017 7:03:00 AM\"\n  },\n  {\n    \"c\": \"149.011\",\n    \"h\": \"149.02\",\n    \"l\": \"149.011\",\n    \"o\": \"149.02\",\n    \"t\": \"Nov 20, 2017 7:04:00 AM\"\n  },\n  {\n    \"c\": \"149.0035\",\n    \"h\": \"149.0165\",\n    \"l\": \"148.9985\",\n    \"o\": \"149.012\",\n    \"t\": \"Nov 20, 2017 7:05:00 AM\"\n  },\n  {\n    \"c\": \"149.012\",\n    \"h\": \"149.012\",\n    \"l\": \"148.9965\",\n    \"o\": \"149.0045\",\n    \"t\": \"Nov 20, 2017 7:06:00 AM\"\n  },\n  {\n    \"c\": \"148.989\",\n    \"h\": \"149.014\",\n    \"l\": \"148.987\",\n    \"o\": \"149.0115\",\n    \"t\": \"Nov 20, 2017 7:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0215\",\n    \"h\": \"149.0225\",\n    \"l\": \"148.991\",\n    \"o\": \"148.991\",\n    \"t\": \"Nov 20, 2017 7:08:00 AM\"\n  },\n  {\n    \"c\": \"149.0195\",\n    \"h\": \"149.024\",\n    \"l\": \"149.019\",\n    \"o\": \"149.019\",\n    \"t\": \"Nov 20, 2017 7:09:00 AM\"\n  },\n  {\n    \"c\": \"149.024\",\n    \"h\": \"149.0255\",\n    \"l\": \"149.017\",\n    \"o\": \"149.018\",\n    \"t\": \"Nov 20, 2017 7:10:00 AM\"\n  },\n  {\n    \"c\": \"149.052\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.02\",\n    \"o\": \"149.0225\",\n    \"t\": \"Nov 20, 2017 7:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0485\",\n    \"h\": \"149.0545\",\n    \"l\": \"149.048\",\n    \"o\": \"149.052\",\n    \"t\": \"Nov 20, 2017 7:12:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.048\",\n    \"l\": \"149.041\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 20, 2017 7:13:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.043\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.043\",\n    \"t\": \"Nov 20, 2017 7:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0335\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.0305\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 20, 2017 7:15:00 AM\"\n  },\n  {\n    \"c\": \"149.0285\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.027\",\n    \"o\": \"149.0325\",\n    \"t\": \"Nov 20, 2017 7:16:00 AM\"\n  },\n  {\n    \"c\": \"149.027\",\n    \"h\": \"149.03\",\n    \"l\": \"149.0225\",\n    \"o\": \"149.0285\",\n    \"t\": \"Nov 20, 2017 7:17:00 AM\"\n  },\n  {\n    \"c\": \"149.0295\",\n    \"h\": \"149.03\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0265\",\n    \"t\": \"Nov 20, 2017 7:18:00 AM\"\n  },\n  {\n    \"c\": \"149.031\",\n    \"h\": \"149.031\",\n    \"l\": \"149.027\",\n    \"o\": \"149.0295\",\n    \"t\": \"Nov 20, 2017 7:19:00 AM\"\n  },\n  {\n    \"c\": \"149.028\",\n    \"h\": \"149.031\",\n    \"l\": \"149.028\",\n    \"o\": \"149.029\",\n    \"t\": \"Nov 20, 2017 7:20:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.0375\",\n    \"l\": \"149.0265\",\n    \"o\": \"149.027\",\n    \"t\": \"Nov 20, 2017 7:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.043\",\n    \"l\": \"149.0325\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 20, 2017 7:22:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.037\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.037\",\n    \"t\": \"Nov 20, 2017 7:23:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.033\",\n    \"o\": \"149.033\",\n    \"t\": \"Nov 20, 2017 7:24:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.03\",\n    \"o\": \"149.033\",\n    \"t\": \"Nov 20, 2017 7:25:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0345\",\n    \"l\": \"149.033\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 20, 2017 7:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0435\",\n    \"l\": \"149.032\",\n    \"o\": \"149.0325\",\n    \"t\": \"Nov 20, 2017 7:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0465\",\n    \"h\": \"149.05\",\n    \"l\": \"149.0425\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 20, 2017 7:28:00 AM\"\n  },\n  {\n    \"c\": \"149.0475\",\n    \"h\": \"149.0485\",\n    \"l\": \"149.0465\",\n    \"o\": \"149.047\",\n    \"t\": \"Nov 20, 2017 7:29:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0595\",\n    \"l\": \"149.048\",\n    \"o\": \"149.048\",\n    \"t\": \"Nov 20, 2017 7:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0595\",\n    \"h\": \"149.06\",\n    \"l\": \"149.057\",\n    \"o\": \"149.057\",\n    \"t\": \"Nov 20, 2017 7:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0605\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.056\",\n    \"o\": \"149.058\",\n    \"t\": \"Nov 20, 2017 7:32:00 AM\"\n  },\n  {\n    \"c\": \"149.067\",\n    \"h\": \"149.07\",\n    \"l\": \"149.059\",\n    \"o\": \"149.062\",\n    \"t\": \"Nov 20, 2017 7:33:00 AM\"\n  },\n  {\n    \"c\": \"149.063\",\n    \"h\": \"149.075\",\n    \"l\": \"149.063\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 20, 2017 7:34:00 AM\"\n  },\n  {\n    \"c\": \"149.062\",\n    \"h\": \"149.065\",\n    \"l\": \"149.0615\",\n    \"o\": \"149.0635\",\n    \"t\": \"Nov 20, 2017 7:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.063\",\n    \"l\": \"149.061\",\n    \"o\": \"149.061\",\n    \"t\": \"Nov 20, 2017 7:36:00 AM\"\n  },\n  {\n    \"c\": \"149.06\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.056\",\n    \"o\": \"149.062\",\n    \"t\": \"Nov 20, 2017 7:37:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.085\",\n    \"l\": \"149.059\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 20, 2017 7:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.085\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 20, 2017 7:39:00 AM\"\n  },\n  {\n    \"c\": \"149.0705\",\n    \"h\": \"149.0735\",\n    \"l\": \"149.0685\",\n    \"o\": \"149.073\",\n    \"t\": \"Nov 20, 2017 7:40:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.074\",\n    \"l\": \"149.0635\",\n    \"o\": \"149.07\",\n    \"t\": \"Nov 20, 2017 7:41:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.077\",\n    \"l\": \"149.058\",\n    \"o\": \"149.0665\",\n    \"t\": \"Nov 20, 2017 7:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0705\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.066\",\n    \"o\": \"149.077\",\n    \"t\": \"Nov 20, 2017 7:43:00 AM\"\n  },\n  {\n    \"c\": \"149.059\",\n    \"h\": \"149.0775\",\n    \"l\": \"149.058\",\n    \"o\": \"149.071\",\n    \"t\": \"Nov 20, 2017 7:44:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.08\",\n    \"l\": \"149.052\",\n    \"o\": \"149.0595\",\n    \"t\": \"Nov 20, 2017 7:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0605\",\n    \"h\": \"149.077\",\n    \"l\": \"149.0605\",\n    \"o\": \"149.0765\",\n    \"t\": \"Nov 20, 2017 7:46:00 AM\"\n  },\n  {\n    \"c\": \"149.044\",\n    \"h\": \"149.0605\",\n    \"l\": \"149.038\",\n    \"o\": \"149.06\",\n    \"t\": \"Nov 20, 2017 7:47:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.063\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 20, 2017 7:48:00 AM\"\n  },\n  {\n    \"c\": \"149.06\",\n    \"h\": \"149.06\",\n    \"l\": \"149.048\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 20, 2017 7:49:00 AM\"\n  },\n  {\n    \"c\": \"149.058\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.0565\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 20, 2017 7:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0555\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.0555\",\n    \"o\": \"149.058\",\n    \"t\": \"Nov 20, 2017 7:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0125\",\n    \"h\": \"149.056\",\n    \"l\": \"149.0125\",\n    \"o\": \"149.054\",\n    \"t\": \"Nov 20, 2017 7:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0165\",\n    \"h\": \"149.02\",\n    \"l\": \"149.0015\",\n    \"o\": \"149.0135\",\n    \"t\": \"Nov 20, 2017 7:53:00 AM\"\n  },\n  {\n    \"c\": \"149.026\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.007\",\n    \"o\": \"149.0145\",\n    \"t\": \"Nov 20, 2017 7:54:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.0355\",\n    \"l\": \"149.0235\",\n    \"o\": \"149.0255\",\n    \"t\": \"Nov 20, 2017 7:55:00 AM\"\n  },\n  {\n    \"c\": \"149.036\",\n    \"h\": \"149.0495\",\n    \"l\": \"149.0305\",\n    \"o\": \"149.0305\",\n    \"t\": \"Nov 20, 2017 7:56:00 AM\"\n  },\n  {\n    \"c\": \"149.041\",\n    \"h\": \"149.042\",\n    \"l\": \"149.036\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 20, 2017 7:57:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.0405\",\n    \"o\": \"149.042\",\n    \"t\": \"Nov 20, 2017 7:58:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.052\",\n    \"l\": \"149.043\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 20, 2017 7:59:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.0565\",\n    \"l\": \"149.032\",\n    \"o\": \"149.047\",\n    \"t\": \"Nov 20, 2017 8:00:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.096\",\n    \"l\": \"149.036\",\n    \"o\": \"149.0425\",\n    \"t\": \"Nov 20, 2017 8:01:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.104\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 20, 2017 8:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1095\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.083\",\n    \"o\": \"149.104\",\n    \"t\": \"Nov 20, 2017 8:03:00 AM\"\n  },\n  {\n    \"c\": \"149.126\",\n    \"h\": \"149.1395\",\n    \"l\": \"149.109\",\n    \"o\": \"149.11\",\n    \"t\": \"Nov 20, 2017 8:04:00 AM\"\n  },\n  {\n    \"c\": \"149.127\",\n    \"h\": \"149.141\",\n    \"l\": \"149.123\",\n    \"o\": \"149.1255\",\n    \"t\": \"Nov 20, 2017 8:05:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.138\",\n    \"l\": \"149.112\",\n    \"o\": \"149.126\",\n    \"t\": \"Nov 20, 2017 8:06:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.1185\",\n    \"l\": \"149.078\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 20, 2017 8:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0825\",\n    \"h\": \"149.0875\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 20, 2017 8:08:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.0665\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 20, 2017 8:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0545\",\n    \"h\": \"149.076\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.0745\",\n    \"t\": \"Nov 20, 2017 8:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0685\",\n    \"h\": \"149.0695\",\n    \"l\": \"149.0525\",\n    \"o\": \"149.053\",\n    \"t\": \"Nov 20, 2017 8:11:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.1025\",\n    \"l\": \"149.063\",\n    \"o\": \"149.068\",\n    \"t\": \"Nov 20, 2017 8:12:00 AM\"\n  },\n  {\n    \"c\": \"149.116\",\n    \"h\": \"149.1195\",\n    \"l\": \"149.0935\",\n    \"o\": \"149.0935\",\n    \"t\": \"Nov 20, 2017 8:13:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.103\",\n    \"o\": \"149.1155\",\n    \"t\": \"Nov 20, 2017 8:14:00 AM\"\n  },\n  {\n    \"c\": \"149.1065\",\n    \"h\": \"149.124\",\n    \"l\": \"149.099\",\n    \"o\": \"149.1025\",\n    \"t\": \"Nov 20, 2017 8:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1125\",\n    \"h\": \"149.1135\",\n    \"l\": \"149.1005\",\n    \"o\": \"149.1075\",\n    \"t\": \"Nov 20, 2017 8:16:00 AM\"\n  },\n  {\n    \"c\": \"149.1295\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1125\",\n    \"o\": \"149.1125\",\n    \"t\": \"Nov 20, 2017 8:17:00 AM\"\n  },\n  {\n    \"c\": \"149.135\",\n    \"h\": \"149.1375\",\n    \"l\": \"149.1225\",\n    \"o\": \"149.1285\",\n    \"t\": \"Nov 20, 2017 8:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.1395\",\n    \"l\": \"149.1325\",\n    \"o\": \"149.135\",\n    \"t\": \"Nov 20, 2017 8:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1615\",\n    \"h\": \"149.17\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1375\",\n    \"t\": \"Nov 20, 2017 8:20:00 AM\"\n  },\n  {\n    \"c\": \"149.1415\",\n    \"h\": \"149.173\",\n    \"l\": \"149.141\",\n    \"o\": \"149.162\",\n    \"t\": \"Nov 20, 2017 8:21:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.153\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1425\",\n    \"t\": \"Nov 20, 2017 8:22:00 AM\"\n  },\n  {\n    \"c\": \"149.131\",\n    \"h\": \"149.1465\",\n    \"l\": \"149.126\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 20, 2017 8:23:00 AM\"\n  },\n  {\n    \"c\": \"149.1325\",\n    \"h\": \"149.1365\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 20, 2017 8:24:00 AM\"\n  },\n  {\n    \"c\": \"149.1565\",\n    \"h\": \"149.157\",\n    \"l\": \"149.1335\",\n    \"o\": \"149.1335\",\n    \"t\": \"Nov 20, 2017 8:25:00 AM\"\n  },\n  {\n    \"c\": \"149.208\",\n    \"h\": \"149.21\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1555\",\n    \"t\": \"Nov 20, 2017 8:26:00 AM\"\n  },\n  {\n    \"c\": \"149.198\",\n    \"h\": \"149.218\",\n    \"l\": \"149.1915\",\n    \"o\": \"149.207\",\n    \"t\": \"Nov 20, 2017 8:27:00 AM\"\n  },\n  {\n    \"c\": \"149.202\",\n    \"h\": \"149.207\",\n    \"l\": \"149.195\",\n    \"o\": \"149.196\",\n    \"t\": \"Nov 20, 2017 8:28:00 AM\"\n  },\n  {\n    \"c\": \"149.216\",\n    \"h\": \"149.2235\",\n    \"l\": \"149.191\",\n    \"o\": \"149.2035\",\n    \"t\": \"Nov 20, 2017 8:29:00 AM\"\n  },\n  {\n    \"c\": \"149.193\",\n    \"h\": \"149.216\",\n    \"l\": \"149.185\",\n    \"o\": \"149.2145\",\n    \"t\": \"Nov 20, 2017 8:30:00 AM\"\n  },\n  {\n    \"c\": \"149.1835\",\n    \"h\": \"149.197\",\n    \"l\": \"149.1835\",\n    \"o\": \"149.193\",\n    \"t\": \"Nov 20, 2017 8:31:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1905\",\n    \"l\": \"149.1735\",\n    \"o\": \"149.182\",\n    \"t\": \"Nov 20, 2017 8:32:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1835\",\n    \"l\": \"149.1705\",\n    \"o\": \"149.174\",\n    \"t\": \"Nov 20, 2017 8:33:00 AM\"\n  },\n  {\n    \"c\": \"149.1795\",\n    \"h\": \"149.187\",\n    \"l\": \"149.1715\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 20, 2017 8:34:00 AM\"\n  },\n  {\n    \"c\": \"149.2055\",\n    \"h\": \"149.209\",\n    \"l\": \"149.1805\",\n    \"o\": \"149.1805\",\n    \"t\": \"Nov 20, 2017 8:35:00 AM\"\n  },\n  {\n    \"c\": \"149.194\",\n    \"h\": \"149.2095\",\n    \"l\": \"149.1925\",\n    \"o\": \"149.2055\",\n    \"t\": \"Nov 20, 2017 8:36:00 AM\"\n  },\n  {\n    \"c\": \"149.1955\",\n    \"h\": \"149.2\",\n    \"l\": \"149.1845\",\n    \"o\": \"149.1935\",\n    \"t\": \"Nov 20, 2017 8:37:00 AM\"\n  },\n  {\n    \"c\": \"149.1995\",\n    \"h\": \"149.211\",\n    \"l\": \"149.184\",\n    \"o\": \"149.194\",\n    \"t\": \"Nov 20, 2017 8:38:00 AM\"\n  },\n  {\n    \"c\": \"149.202\",\n    \"h\": \"149.206\",\n    \"l\": \"149.1905\",\n    \"o\": \"149.199\",\n    \"t\": \"Nov 20, 2017 8:39:00 AM\"\n  },\n  {\n    \"c\": \"149.184\",\n    \"h\": \"149.2025\",\n    \"l\": \"149.17\",\n    \"o\": \"149.202\",\n    \"t\": \"Nov 20, 2017 8:40:00 AM\"\n  },\n  {\n    \"c\": \"149.187\",\n    \"h\": \"149.1945\",\n    \"l\": \"149.174\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 20, 2017 8:41:00 AM\"\n  }\n]"
  },
  {
    "path": "app/src/main/assets/timesharing1.json",
    "content": "[\n  {\n    \"c\": \"148.942\",\n    \"h\": \"148.9445\",\n    \"l\": \"148.9245\",\n    \"o\": \"148.926\",\n    \"t\": \"Nov 21, 2017 2:45:00 AM\"\n  },\n  {\n    \"c\": \"148.9105\",\n    \"h\": \"148.9445\",\n    \"l\": \"148.9075\",\n    \"o\": \"148.942\",\n    \"t\": \"Nov 21, 2017 2:46:00 AM\"\n  },\n  {\n    \"c\": \"148.9175\",\n    \"h\": \"148.9175\",\n    \"l\": \"148.878\",\n    \"o\": \"148.906\",\n    \"t\": \"Nov 21, 2017 2:47:00 AM\"\n  },\n  {\n    \"c\": \"148.9155\",\n    \"h\": \"148.933\",\n    \"l\": \"148.905\",\n    \"o\": \"148.9175\",\n    \"t\": \"Nov 21, 2017 2:48:00 AM\"\n  },\n  {\n    \"c\": \"148.9035\",\n    \"h\": \"148.9195\",\n    \"l\": \"148.8955\",\n    \"o\": \"148.916\",\n    \"t\": \"Nov 21, 2017 2:49:00 AM\"\n  },\n  {\n    \"c\": \"148.9045\",\n    \"h\": \"148.9075\",\n    \"l\": \"148.8975\",\n    \"o\": \"148.9035\",\n    \"t\": \"Nov 21, 2017 2:50:00 AM\"\n  },\n  {\n    \"c\": \"148.9\",\n    \"h\": \"148.9045\",\n    \"l\": \"148.9\",\n    \"o\": \"148.9045\",\n    \"t\": \"Nov 21, 2017 2:51:00 AM\"\n  },\n  {\n    \"c\": \"148.9025\",\n    \"h\": \"148.908\",\n    \"l\": \"148.8915\",\n    \"o\": \"148.9005\",\n    \"t\": \"Nov 21, 2017 2:52:00 AM\"\n  },\n  {\n    \"c\": \"148.926\",\n    \"h\": \"148.926\",\n    \"l\": \"148.9015\",\n    \"o\": \"148.9015\",\n    \"t\": \"Nov 21, 2017 2:53:00 AM\"\n  },\n  {\n    \"c\": \"148.9105\",\n    \"h\": \"148.926\",\n    \"l\": \"148.91\",\n    \"o\": \"148.926\",\n    \"t\": \"Nov 21, 2017 2:54:00 AM\"\n  },\n  {\n    \"c\": \"148.9265\",\n    \"h\": \"148.941\",\n    \"l\": \"148.91\",\n    \"o\": \"148.91\",\n    \"t\": \"Nov 21, 2017 2:55:00 AM\"\n  },\n  {\n    \"c\": \"148.933\",\n    \"h\": \"148.9455\",\n    \"l\": \"148.9255\",\n    \"o\": \"148.9265\",\n    \"t\": \"Nov 21, 2017 2:56:00 AM\"\n  },\n  {\n    \"c\": \"148.94\",\n    \"h\": \"148.952\",\n    \"l\": \"148.932\",\n    \"o\": \"148.9325\",\n    \"t\": \"Nov 21, 2017 2:57:00 AM\"\n  },\n  {\n    \"c\": \"148.9325\",\n    \"h\": \"148.9465\",\n    \"l\": \"148.928\",\n    \"o\": \"148.94\",\n    \"t\": \"Nov 21, 2017 2:58:00 AM\"\n  },\n  {\n    \"c\": \"148.937\",\n    \"h\": \"148.9395\",\n    \"l\": \"148.913\",\n    \"o\": \"148.932\",\n    \"t\": \"Nov 21, 2017 2:59:00 AM\"\n  },\n  {\n    \"c\": \"148.9635\",\n    \"h\": \"148.9655\",\n    \"l\": \"148.937\",\n    \"o\": \"148.937\",\n    \"t\": \"Nov 21, 2017 3:00:00 AM\"\n  },\n  {\n    \"c\": \"148.973\",\n    \"h\": \"148.978\",\n    \"l\": \"148.962\",\n    \"o\": \"148.962\",\n    \"t\": \"Nov 21, 2017 3:01:00 AM\"\n  },\n  {\n    \"c\": \"148.9725\",\n    \"h\": \"148.976\",\n    \"l\": \"148.966\",\n    \"o\": \"148.9725\",\n    \"t\": \"Nov 21, 2017 3:02:00 AM\"\n  },\n  {\n    \"c\": \"148.975\",\n    \"h\": \"148.975\",\n    \"l\": \"148.965\",\n    \"o\": \"148.9725\",\n    \"t\": \"Nov 21, 2017 3:03:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.03\",\n    \"l\": \"148.9635\",\n    \"o\": \"148.976\",\n    \"t\": \"Nov 21, 2017 3:04:00 AM\"\n  },\n  {\n    \"c\": \"148.972\",\n    \"h\": \"149.093\",\n    \"l\": \"148.9695\",\n    \"o\": \"149.024\",\n    \"t\": \"Nov 21, 2017 3:05:00 AM\"\n  },\n  {\n    \"c\": \"148.981\",\n    \"h\": \"148.981\",\n    \"l\": \"148.9615\",\n    \"o\": \"148.973\",\n    \"t\": \"Nov 21, 2017 3:06:00 AM\"\n  },\n  {\n    \"c\": \"148.9825\",\n    \"h\": \"148.9885\",\n    \"l\": \"148.9755\",\n    \"o\": \"148.981\",\n    \"t\": \"Nov 21, 2017 3:07:00 AM\"\n  },\n  {\n    \"c\": \"148.9695\",\n    \"h\": \"148.994\",\n    \"l\": \"148.9665\",\n    \"o\": \"148.982\",\n    \"t\": \"Nov 21, 2017 3:08:00 AM\"\n  },\n  {\n    \"c\": \"148.9675\",\n    \"h\": \"148.9815\",\n    \"l\": \"148.9635\",\n    \"o\": \"148.97\",\n    \"t\": \"Nov 21, 2017 3:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0195\",\n    \"h\": \"149.0215\",\n    \"l\": \"148.963\",\n    \"o\": \"148.9675\",\n    \"t\": \"Nov 21, 2017 3:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.0355\",\n    \"l\": \"149.005\",\n    \"o\": \"149.0185\",\n    \"t\": \"Nov 21, 2017 3:11:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.036\",\n    \"t\": \"Nov 21, 2017 3:12:00 AM\"\n  },\n  {\n    \"c\": \"149.02\",\n    \"h\": \"149.0315\",\n    \"l\": \"149.016\",\n    \"o\": \"149.0295\",\n    \"t\": \"Nov 21, 2017 3:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.071\",\n    \"l\": \"149.0195\",\n    \"o\": \"149.0215\",\n    \"t\": \"Nov 21, 2017 3:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0655\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.032\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 3:15:00 AM\"\n  },\n  {\n    \"c\": \"149.065\",\n    \"h\": \"149.0795\",\n    \"l\": \"149.059\",\n    \"o\": \"149.0655\",\n    \"t\": \"Nov 21, 2017 3:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.09\",\n    \"l\": \"149.062\",\n    \"o\": \"149.0645\",\n    \"t\": \"Nov 21, 2017 3:17:00 AM\"\n  },\n  {\n    \"c\": \"149.078\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.06\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 3:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.086\",\n    \"l\": \"149.0755\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 3:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1755\",\n    \"l\": \"149.085\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 3:20:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.178\",\n    \"l\": \"149.103\",\n    \"o\": \"149.1735\",\n    \"t\": \"Nov 21, 2017 3:21:00 AM\"\n  },\n  {\n    \"c\": \"149.1395\",\n    \"h\": \"149.149\",\n    \"l\": \"149.1255\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 3:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1385\",\n    \"t\": \"Nov 21, 2017 3:23:00 AM\"\n  },\n  {\n    \"c\": \"149.157\",\n    \"h\": \"149.1615\",\n    \"l\": \"149.1475\",\n    \"o\": \"149.1595\",\n    \"t\": \"Nov 21, 2017 3:24:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.158\",\n    \"l\": \"149.131\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 3:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.157\",\n    \"l\": \"149.145\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 3:26:00 AM\"\n  },\n  {\n    \"c\": \"149.165\",\n    \"h\": \"149.171\",\n    \"l\": \"149.1475\",\n    \"o\": \"149.1485\",\n    \"t\": \"Nov 21, 2017 3:27:00 AM\"\n  },\n  {\n    \"c\": \"149.178\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1635\",\n    \"t\": \"Nov 21, 2017 3:28:00 AM\"\n  },\n  {\n    \"c\": \"149.19\",\n    \"h\": \"149.19\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.178\",\n    \"t\": \"Nov 21, 2017 3:29:00 AM\"\n  },\n  {\n    \"c\": \"149.1835\",\n    \"h\": \"149.198\",\n    \"l\": \"149.177\",\n    \"o\": \"149.191\",\n    \"t\": \"Nov 21, 2017 3:30:00 AM\"\n  },\n  {\n    \"c\": \"149.177\",\n    \"h\": \"149.187\",\n    \"l\": \"149.167\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 3:31:00 AM\"\n  },\n  {\n    \"c\": \"149.1725\",\n    \"h\": \"149.1855\",\n    \"l\": \"149.1685\",\n    \"o\": \"149.1775\",\n    \"t\": \"Nov 21, 2017 3:32:00 AM\"\n  },\n  {\n    \"c\": \"149.193\",\n    \"h\": \"149.195\",\n    \"l\": \"149.168\",\n    \"o\": \"149.1725\",\n    \"t\": \"Nov 21, 2017 3:33:00 AM\"\n  },\n  {\n    \"c\": \"149.191\",\n    \"h\": \"149.204\",\n    \"l\": \"149.1825\",\n    \"o\": \"149.1935\",\n    \"t\": \"Nov 21, 2017 3:34:00 AM\"\n  },\n  {\n    \"c\": \"149.195\",\n    \"h\": \"149.198\",\n    \"l\": \"149.1825\",\n    \"o\": \"149.1905\",\n    \"t\": \"Nov 21, 2017 3:35:00 AM\"\n  },\n  {\n    \"c\": \"149.197\",\n    \"h\": \"149.2395\",\n    \"l\": \"149.193\",\n    \"o\": \"149.196\",\n    \"t\": \"Nov 21, 2017 3:36:00 AM\"\n  },\n  {\n    \"c\": \"149.2235\",\n    \"h\": \"149.232\",\n    \"l\": \"149.193\",\n    \"o\": \"149.197\",\n    \"t\": \"Nov 21, 2017 3:37:00 AM\"\n  },\n  {\n    \"c\": \"149.2065\",\n    \"h\": \"149.2355\",\n    \"l\": \"149.2065\",\n    \"o\": \"149.224\",\n    \"t\": \"Nov 21, 2017 3:38:00 AM\"\n  },\n  {\n    \"c\": \"149.2145\",\n    \"h\": \"149.2185\",\n    \"l\": \"149.2075\",\n    \"o\": \"149.2075\",\n    \"t\": \"Nov 21, 2017 3:39:00 AM\"\n  },\n  {\n    \"c\": \"149.2075\",\n    \"h\": \"149.2145\",\n    \"l\": \"149.2045\",\n    \"o\": \"149.2145\",\n    \"t\": \"Nov 21, 2017 3:40:00 AM\"\n  },\n  {\n    \"c\": \"149.1765\",\n    \"h\": \"149.2125\",\n    \"l\": \"149.1765\",\n    \"o\": \"149.2085\",\n    \"t\": \"Nov 21, 2017 3:41:00 AM\"\n  },\n  {\n    \"c\": \"149.171\",\n    \"h\": \"149.189\",\n    \"l\": \"149.1655\",\n    \"o\": \"149.1775\",\n    \"t\": \"Nov 21, 2017 3:42:00 AM\"\n  },\n  {\n    \"c\": \"149.183\",\n    \"h\": \"149.188\",\n    \"l\": \"149.165\",\n    \"o\": \"149.171\",\n    \"t\": \"Nov 21, 2017 3:43:00 AM\"\n  },\n  {\n    \"c\": \"149.181\",\n    \"h\": \"149.1925\",\n    \"l\": \"149.1685\",\n    \"o\": \"149.183\",\n    \"t\": \"Nov 21, 2017 3:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1775\",\n    \"h\": \"149.192\",\n    \"l\": \"149.172\",\n    \"o\": \"149.179\",\n    \"t\": \"Nov 21, 2017 3:45:00 AM\"\n  },\n  {\n    \"c\": \"149.174\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1765\",\n    \"t\": \"Nov 21, 2017 3:46:00 AM\"\n  },\n  {\n    \"c\": \"149.17\",\n    \"h\": \"149.1885\",\n    \"l\": \"149.17\",\n    \"o\": \"149.1745\",\n    \"t\": \"Nov 21, 2017 3:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.166\",\n    \"o\": \"149.1705\",\n    \"t\": \"Nov 21, 2017 3:48:00 AM\"\n  },\n  {\n    \"c\": \"149.1815\",\n    \"h\": \"149.1875\",\n    \"l\": \"149.1735\",\n    \"o\": \"149.1735\",\n    \"t\": \"Nov 21, 2017 3:49:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.181\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.1805\",\n    \"t\": \"Nov 21, 2017 3:50:00 AM\"\n  },\n  {\n    \"c\": \"149.1465\",\n    \"h\": \"149.162\",\n    \"l\": \"149.1455\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 3:51:00 AM\"\n  },\n  {\n    \"c\": \"149.1545\",\n    \"h\": \"149.1625\",\n    \"l\": \"149.141\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 3:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1405\",\n    \"h\": \"149.163\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1545\",\n    \"t\": \"Nov 21, 2017 3:53:00 AM\"\n  },\n  {\n    \"c\": \"149.148\",\n    \"h\": \"149.1505\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1405\",\n    \"t\": \"Nov 21, 2017 3:54:00 AM\"\n  },\n  {\n    \"c\": \"149.153\",\n    \"h\": \"149.156\",\n    \"l\": \"149.129\",\n    \"o\": \"149.148\",\n    \"t\": \"Nov 21, 2017 3:55:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.154\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1535\",\n    \"t\": \"Nov 21, 2017 3:56:00 AM\"\n  },\n  {\n    \"c\": \"149.163\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 3:57:00 AM\"\n  },\n  {\n    \"c\": \"149.166\",\n    \"h\": \"149.174\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.163\",\n    \"t\": \"Nov 21, 2017 3:58:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1435\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 3:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1245\",\n    \"h\": \"149.1515\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 4:00:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.1295\",\n    \"l\": \"149.115\",\n    \"o\": \"149.1245\",\n    \"t\": \"Nov 21, 2017 4:01:00 AM\"\n  },\n  {\n    \"c\": \"149.119\",\n    \"h\": \"149.125\",\n    \"l\": \"149.1145\",\n    \"o\": \"149.116\",\n    \"t\": \"Nov 21, 2017 4:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1325\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.11\",\n    \"o\": \"149.1185\",\n    \"t\": \"Nov 21, 2017 4:03:00 AM\"\n  },\n  {\n    \"c\": \"149.152\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1325\",\n    \"o\": \"149.1325\",\n    \"t\": \"Nov 21, 2017 4:04:00 AM\"\n  },\n  {\n    \"c\": \"149.161\",\n    \"h\": \"149.164\",\n    \"l\": \"149.152\",\n    \"o\": \"149.152\",\n    \"t\": \"Nov 21, 2017 4:05:00 AM\"\n  },\n  {\n    \"c\": \"149.1595\",\n    \"h\": \"149.169\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1615\",\n    \"t\": \"Nov 21, 2017 4:06:00 AM\"\n  },\n  {\n    \"c\": \"149.1475\",\n    \"h\": \"149.166\",\n    \"l\": \"149.144\",\n    \"o\": \"149.1595\",\n    \"t\": \"Nov 21, 2017 4:07:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.152\",\n    \"l\": \"149.137\",\n    \"o\": \"149.148\",\n    \"t\": \"Nov 21, 2017 4:08:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.1485\",\n    \"l\": \"149.1345\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 4:09:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.144\",\n    \"l\": \"149.1265\",\n    \"o\": \"149.137\",\n    \"t\": \"Nov 21, 2017 4:10:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.152\",\n    \"l\": \"149.1365\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 4:11:00 AM\"\n  },\n  {\n    \"c\": \"149.1355\",\n    \"h\": \"149.1475\",\n    \"l\": \"149.133\",\n    \"o\": \"149.1475\",\n    \"t\": \"Nov 21, 2017 4:12:00 AM\"\n  },\n  {\n    \"c\": \"149.116\",\n    \"h\": \"149.138\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1355\",\n    \"t\": \"Nov 21, 2017 4:13:00 AM\"\n  },\n  {\n    \"c\": \"149.13\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1165\",\n    \"t\": \"Nov 21, 2017 4:14:00 AM\"\n  },\n  {\n    \"c\": \"149.124\",\n    \"h\": \"149.13\",\n    \"l\": \"149.1195\",\n    \"o\": \"149.1295\",\n    \"t\": \"Nov 21, 2017 4:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1265\",\n    \"h\": \"149.1285\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.1245\",\n    \"t\": \"Nov 21, 2017 4:16:00 AM\"\n  },\n  {\n    \"c\": \"149.123\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.112\",\n    \"o\": \"149.128\",\n    \"t\": \"Nov 21, 2017 4:17:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.126\",\n    \"l\": \"149.109\",\n    \"o\": \"149.1225\",\n    \"t\": \"Nov 21, 2017 4:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1125\",\n    \"h\": \"149.123\",\n    \"l\": \"149.11\",\n    \"o\": \"149.1145\",\n    \"t\": \"Nov 21, 2017 4:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.117\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.112\",\n    \"t\": \"Nov 21, 2017 4:20:00 AM\"\n  },\n  {\n    \"c\": \"149.106\",\n    \"h\": \"149.115\",\n    \"l\": \"149.1045\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 4:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.105\",\n    \"l\": \"149.094\",\n    \"o\": \"149.1045\",\n    \"t\": \"Nov 21, 2017 4:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1195\",\n    \"h\": \"149.1195\",\n    \"l\": \"149.095\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 4:23:00 AM\"\n  },\n  {\n    \"c\": \"149.123\",\n    \"h\": \"149.1305\",\n    \"l\": \"149.115\",\n    \"o\": \"149.119\",\n    \"t\": \"Nov 21, 2017 4:24:00 AM\"\n  },\n  {\n    \"c\": \"149.134\",\n    \"h\": \"149.1355\",\n    \"l\": \"149.1215\",\n    \"o\": \"149.122\",\n    \"t\": \"Nov 21, 2017 4:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1215\",\n    \"h\": \"149.137\",\n    \"l\": \"149.12\",\n    \"o\": \"149.134\",\n    \"t\": \"Nov 21, 2017 4:26:00 AM\"\n  },\n  {\n    \"c\": \"149.1335\",\n    \"h\": \"149.137\",\n    \"l\": \"149.118\",\n    \"o\": \"149.1205\",\n    \"t\": \"Nov 21, 2017 4:27:00 AM\"\n  },\n  {\n    \"c\": \"149.144\",\n    \"h\": \"149.1525\",\n    \"l\": \"149.134\",\n    \"o\": \"149.134\",\n    \"t\": \"Nov 21, 2017 4:28:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.1585\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.1445\",\n    \"t\": \"Nov 21, 2017 4:29:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.151\",\n    \"l\": \"149.136\",\n    \"o\": \"149.1435\",\n    \"t\": \"Nov 21, 2017 4:30:00 AM\"\n  },\n  {\n    \"c\": \"149.114\",\n    \"h\": \"149.147\",\n    \"l\": \"149.114\",\n    \"o\": \"149.146\",\n    \"t\": \"Nov 21, 2017 4:31:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.1025\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 4:32:00 AM\"\n  },\n  {\n    \"c\": \"149.0985\",\n    \"h\": \"149.1115\",\n    \"l\": \"149.096\",\n    \"o\": \"149.1035\",\n    \"t\": \"Nov 21, 2017 4:33:00 AM\"\n  },\n  {\n    \"c\": \"149.0995\",\n    \"h\": \"149.1005\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 4:34:00 AM\"\n  },\n  {\n    \"c\": \"149.088\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 4:35:00 AM\"\n  },\n  {\n    \"c\": \"149.089\",\n    \"h\": \"149.089\",\n    \"l\": \"149.082\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 4:36:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.095\",\n    \"l\": \"149.0815\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 4:37:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 4:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0945\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.09\",\n    \"t\": \"Nov 21, 2017 4:39:00 AM\"\n  },\n  {\n    \"c\": \"149.098\",\n    \"h\": \"149.099\",\n    \"l\": \"149.0835\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 4:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0815\",\n    \"h\": \"149.0995\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.098\",\n    \"t\": \"Nov 21, 2017 4:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0875\",\n    \"h\": \"149.092\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 4:42:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 4:43:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.079\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 4:44:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.0795\",\n    \"t\": \"Nov 21, 2017 4:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.0715\",\n    \"o\": \"149.075\",\n    \"t\": \"Nov 21, 2017 4:46:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.079\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 4:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0835\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.077\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 4:48:00 AM\"\n  },\n  {\n    \"c\": \"149.0765\",\n    \"h\": \"149.083\",\n    \"l\": \"149.073\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 4:49:00 AM\"\n  },\n  {\n    \"c\": \"149.069\",\n    \"h\": \"149.078\",\n    \"l\": \"149.0665\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 4:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.076\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.07\",\n    \"t\": \"Nov 21, 2017 4:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0735\",\n    \"h\": \"149.076\",\n    \"l\": \"149.064\",\n    \"o\": \"149.0725\",\n    \"t\": \"Nov 21, 2017 4:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0675\",\n    \"h\": \"149.0735\",\n    \"l\": \"149.063\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 4:53:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.083\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.067\",\n    \"t\": \"Nov 21, 2017 4:54:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0645\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 4:55:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.0795\",\n    \"l\": \"149.061\",\n    \"o\": \"149.0785\",\n    \"t\": \"Nov 21, 2017 4:56:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.0655\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 4:57:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 4:58:00 AM\"\n  },\n  {\n    \"c\": \"149.031\",\n    \"h\": \"149.0545\",\n    \"l\": \"149.025\",\n    \"o\": \"149.043\",\n    \"t\": \"Nov 21, 2017 4:59:00 AM\"\n  },\n  {\n    \"c\": \"149.0095\",\n    \"h\": \"149.0455\",\n    \"l\": \"149.002\",\n    \"o\": \"149.0305\",\n    \"t\": \"Nov 21, 2017 5:00:00 AM\"\n  },\n  {\n    \"c\": \"149.007\",\n    \"h\": \"149.015\",\n    \"l\": \"149.0\",\n    \"o\": \"149.01\",\n    \"t\": \"Nov 21, 2017 5:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0045\",\n    \"h\": \"149.0095\",\n    \"l\": \"149.0\",\n    \"o\": \"149.008\",\n    \"t\": \"Nov 21, 2017 5:02:00 AM\"\n  },\n  {\n    \"c\": \"148.997\",\n    \"h\": \"149.0035\",\n    \"l\": \"148.9915\",\n    \"o\": \"149.0035\",\n    \"t\": \"Nov 21, 2017 5:03:00 AM\"\n  },\n  {\n    \"c\": \"148.989\",\n    \"h\": \"148.998\",\n    \"l\": \"148.985\",\n    \"o\": \"148.997\",\n    \"t\": \"Nov 21, 2017 5:04:00 AM\"\n  },\n  {\n    \"c\": \"148.9855\",\n    \"h\": \"149.0\",\n    \"l\": \"148.9825\",\n    \"o\": \"148.99\",\n    \"t\": \"Nov 21, 2017 5:05:00 AM\"\n  },\n  {\n    \"c\": \"148.977\",\n    \"h\": \"148.9935\",\n    \"l\": \"148.974\",\n    \"o\": \"148.986\",\n    \"t\": \"Nov 21, 2017 5:06:00 AM\"\n  },\n  {\n    \"c\": \"148.97\",\n    \"h\": \"148.9815\",\n    \"l\": \"148.961\",\n    \"o\": \"148.9765\",\n    \"t\": \"Nov 21, 2017 5:07:00 AM\"\n  },\n  {\n    \"c\": \"148.9865\",\n    \"h\": \"148.988\",\n    \"l\": \"148.9675\",\n    \"o\": \"148.9695\",\n    \"t\": \"Nov 21, 2017 5:08:00 AM\"\n  },\n  {\n    \"c\": \"149.002\",\n    \"h\": \"149.002\",\n    \"l\": \"148.9855\",\n    \"o\": \"148.9865\",\n    \"t\": \"Nov 21, 2017 5:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0085\",\n    \"h\": \"149.014\",\n    \"l\": \"148.9905\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:10:00 AM\"\n  },\n  {\n    \"c\": \"149.007\",\n    \"h\": \"149.0085\",\n    \"l\": \"148.9965\",\n    \"o\": \"149.0075\",\n    \"t\": \"Nov 21, 2017 5:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0185\",\n    \"h\": \"149.0185\",\n    \"l\": \"149.007\",\n    \"o\": \"149.007\",\n    \"t\": \"Nov 21, 2017 5:12:00 AM\"\n  },\n  {\n    \"c\": \"149.0165\",\n    \"h\": \"149.0215\",\n    \"l\": \"149.0135\",\n    \"o\": \"149.0185\",\n    \"t\": \"Nov 21, 2017 5:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0305\",\n    \"h\": \"149.033\",\n    \"l\": \"149.0145\",\n    \"o\": \"149.0175\",\n    \"t\": \"Nov 21, 2017 5:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0365\",\n    \"h\": \"149.0375\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.03\",\n    \"t\": \"Nov 21, 2017 5:15:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.04\",\n    \"l\": \"149.033\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 5:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.047\",\n    \"l\": \"149.0375\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 5:17:00 AM\"\n  },\n  {\n    \"c\": \"149.0455\",\n    \"h\": \"149.051\",\n    \"l\": \"149.038\",\n    \"o\": \"149.0405\",\n    \"t\": \"Nov 21, 2017 5:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0535\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0455\",\n    \"o\": \"149.0455\",\n    \"t\": \"Nov 21, 2017 5:19:00 AM\"\n  },\n  {\n    \"c\": \"149.055\",\n    \"h\": \"149.059\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 5:20:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.0455\",\n    \"o\": \"149.055\",\n    \"t\": \"Nov 21, 2017 5:21:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0495\",\n    \"o\": \"149.0635\",\n    \"t\": \"Nov 21, 2017 5:22:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.051\",\n    \"t\": \"Nov 21, 2017 5:23:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0645\",\n    \"l\": \"149.046\",\n    \"o\": \"149.0645\",\n    \"t\": \"Nov 21, 2017 5:24:00 AM\"\n  },\n  {\n    \"c\": \"149.0645\",\n    \"h\": \"149.0645\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.056\",\n    \"t\": \"Nov 21, 2017 5:25:00 AM\"\n  },\n  {\n    \"c\": \"149.076\",\n    \"h\": \"149.077\",\n    \"l\": \"149.063\",\n    \"o\": \"149.063\",\n    \"t\": \"Nov 21, 2017 5:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0805\",\n    \"l\": \"149.0725\",\n    \"o\": \"149.0755\",\n    \"t\": \"Nov 21, 2017 5:27:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.087\",\n    \"l\": \"149.08\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 5:28:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.084\",\n    \"t\": \"Nov 21, 2017 5:29:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 5:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0975\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 5:31:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.1015\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 5:32:00 AM\"\n  },\n  {\n    \"c\": \"149.107\",\n    \"h\": \"149.1095\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.0835\",\n    \"t\": \"Nov 21, 2017 5:33:00 AM\"\n  },\n  {\n    \"c\": \"149.1025\",\n    \"h\": \"149.113\",\n    \"l\": \"149.095\",\n    \"o\": \"149.1055\",\n    \"t\": \"Nov 21, 2017 5:34:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.1035\",\n    \"l\": \"149.0935\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 5:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.097\",\n    \"l\": \"149.091\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 5:36:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0835\",\n    \"o\": \"149.0925\",\n    \"t\": \"Nov 21, 2017 5:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0755\",\n    \"h\": \"149.087\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 5:38:00 AM\"\n  },\n  {\n    \"c\": \"149.05\",\n    \"h\": \"149.078\",\n    \"l\": \"149.0495\",\n    \"o\": \"149.0765\",\n    \"t\": \"Nov 21, 2017 5:39:00 AM\"\n  },\n  {\n    \"c\": \"149.018\",\n    \"h\": \"149.051\",\n    \"l\": \"149.0155\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 5:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0365\",\n    \"h\": \"149.037\",\n    \"l\": \"149.0175\",\n    \"o\": \"149.018\",\n    \"t\": \"Nov 21, 2017 5:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.0375\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 5:42:00 AM\"\n  },\n  {\n    \"c\": \"149.057\",\n    \"h\": \"149.07\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 5:43:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0575\",\n    \"t\": \"Nov 21, 2017 5:44:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.074\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.0655\",\n    \"t\": \"Nov 21, 2017 5:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.084\",\n    \"l\": \"149.0725\",\n    \"o\": \"149.0735\",\n    \"t\": \"Nov 21, 2017 5:46:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.08\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 5:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0685\",\n    \"h\": \"149.0775\",\n    \"l\": \"149.068\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 5:48:00 AM\"\n  },\n  {\n    \"c\": \"149.067\",\n    \"h\": \"149.0685\",\n    \"l\": \"149.066\",\n    \"o\": \"149.067\",\n    \"t\": \"Nov 21, 2017 5:49:00 AM\"\n  },\n  {\n    \"c\": \"149.045\",\n    \"h\": \"149.073\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.066\",\n    \"t\": \"Nov 21, 2017 5:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.046\",\n    \"l\": \"149.0225\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 5:51:00 AM\"\n  },\n  {\n    \"c\": \"149.004\",\n    \"h\": \"149.023\",\n    \"l\": \"149.004\",\n    \"o\": \"149.023\",\n    \"t\": \"Nov 21, 2017 5:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0175\",\n    \"h\": \"149.022\",\n    \"l\": \"149.0045\",\n    \"o\": \"149.0045\",\n    \"t\": \"Nov 21, 2017 5:53:00 AM\"\n  },\n  {\n    \"c\": \"149.011\",\n    \"h\": \"149.0195\",\n    \"l\": \"149.008\",\n    \"o\": \"149.0175\",\n    \"t\": \"Nov 21, 2017 5:54:00 AM\"\n  },\n  {\n    \"c\": \"149.009\",\n    \"h\": \"149.0115\",\n    \"l\": \"149.001\",\n    \"o\": \"149.0115\",\n    \"t\": \"Nov 21, 2017 5:55:00 AM\"\n  },\n  {\n    \"c\": \"149.001\",\n    \"h\": \"149.0155\",\n    \"l\": \"148.9975\",\n    \"o\": \"149.007\",\n    \"t\": \"Nov 21, 2017 5:56:00 AM\"\n  },\n  {\n    \"c\": \"149.0025\",\n    \"h\": \"149.005\",\n    \"l\": \"148.998\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:57:00 AM\"\n  },\n  {\n    \"c\": \"149.041\",\n    \"h\": \"149.0555\",\n    \"l\": \"149.0025\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:58:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.069\",\n    \"l\": \"149.033\",\n    \"o\": \"149.042\",\n    \"t\": \"Nov 21, 2017 5:59:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.0805\",\n    \"l\": \"149.0405\",\n    \"o\": \"149.0805\",\n    \"t\": \"Nov 21, 2017 6:00:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.039\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 6:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0415\",\n    \"h\": \"149.0415\",\n    \"l\": \"149.0355\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:02:00 AM\"\n  },\n  {\n    \"c\": \"149.0635\",\n    \"h\": \"149.0635\",\n    \"l\": \"149.0415\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 6:03:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.1045\",\n    \"l\": \"149.064\",\n    \"o\": \"149.064\",\n    \"t\": \"Nov 21, 2017 6:04:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.105\",\n    \"l\": \"149.0915\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 6:05:00 AM\"\n  },\n  {\n    \"c\": \"149.0815\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0925\",\n    \"t\": \"Nov 21, 2017 6:06:00 AM\"\n  },\n  {\n    \"c\": \"149.0875\",\n    \"h\": \"149.0885\",\n    \"l\": \"149.082\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 6:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0925\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:08:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.0945\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0935\",\n    \"t\": \"Nov 21, 2017 6:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.088\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:11:00 AM\"\n  },\n  {\n    \"c\": \"149.097\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0945\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 6:12:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0965\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.097\",\n    \"l\": \"149.0965\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:14:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.092\",\n    \"o\": \"149.095\",\n    \"t\": \"Nov 21, 2017 6:15:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.099\",\n    \"l\": \"149.094\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 6:17:00 AM\"\n  },\n  {\n    \"c\": \"149.1015\",\n    \"h\": \"149.102\",\n    \"l\": \"149.0885\",\n    \"o\": \"149.091\",\n    \"t\": \"Nov 21, 2017 6:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0955\",\n    \"h\": \"149.107\",\n    \"l\": \"149.0905\",\n    \"o\": \"149.1005\",\n    \"t\": \"Nov 21, 2017 6:19:00 AM\"\n  },\n  {\n    \"c\": \"149.0935\",\n    \"h\": \"149.105\",\n    \"l\": \"149.0905\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 6:20:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.094\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 6:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0925\",\n    \"h\": \"149.096\",\n    \"l\": \"149.0925\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 6:22:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0855\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:23:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.09\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:24:00 AM\"\n  },\n  {\n    \"c\": \"149.088\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:25:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.0875\",\n    \"l\": \"149.084\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 6:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.0635\",\n    \"o\": \"149.0825\",\n    \"t\": \"Nov 21, 2017 6:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.0865\",\n    \"l\": \"149.078\",\n    \"o\": \"149.0795\",\n    \"t\": \"Nov 21, 2017 6:28:00 AM\"\n  },\n  {\n    \"c\": \"149.065\",\n    \"h\": \"149.0885\",\n    \"l\": \"149.062\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 6:29:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.065\",\n    \"l\": \"149.052\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 6:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.094\",\n    \"l\": \"149.061\",\n    \"o\": \"149.0625\",\n    \"t\": \"Nov 21, 2017 6:31:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:32:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.088\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 6:33:00 AM\"\n  },\n  {\n    \"c\": \"149.089\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:34:00 AM\"\n  },\n  {\n    \"c\": \"149.0865\",\n    \"h\": \"149.095\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:35:00 AM\"\n  },\n  {\n    \"c\": \"149.097\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 6:36:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 6:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.095\",\n    \"l\": \"149.067\",\n    \"o\": \"149.092\",\n    \"t\": \"Nov 21, 2017 6:38:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.0815\",\n    \"l\": \"149.074\",\n    \"o\": \"149.074\",\n    \"t\": \"Nov 21, 2017 6:39:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 6:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0785\",\n    \"h\": \"149.08\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.077\",\n    \"t\": \"Nov 21, 2017 6:41:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 6:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0765\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.076\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 6:43:00 AM\"\n  },\n  {\n    \"c\": \"149.075\",\n    \"h\": \"149.0765\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 6:44:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0745\",\n    \"l\": \"149.053\",\n    \"o\": \"149.0745\",\n    \"t\": \"Nov 21, 2017 6:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0375\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0355\",\n    \"o\": \"149.0555\",\n    \"t\": \"Nov 21, 2017 6:46:00 AM\"\n  },\n  {\n    \"c\": \"149.0415\",\n    \"h\": \"149.0425\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.0395\",\n    \"t\": \"Nov 21, 2017 6:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0445\",\n    \"h\": \"149.045\",\n    \"l\": \"149.04\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:48:00 AM\"\n  },\n  {\n    \"c\": \"149.059\",\n    \"h\": \"149.06\",\n    \"l\": \"149.045\",\n    \"o\": \"149.0455\",\n    \"t\": \"Nov 21, 2017 6:49:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.059\",\n    \"l\": \"149.049\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 6:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.054\",\n    \"l\": \"149.05\",\n    \"o\": \"149.0515\",\n    \"t\": \"Nov 21, 2017 6:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.052\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.052\",\n    \"t\": \"Nov 21, 2017 6:52:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.0475\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:53:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.04\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 6:54:00 AM\"\n  },\n  {\n    \"c\": \"149.0345\",\n    \"h\": \"149.04\",\n    \"l\": \"149.034\",\n    \"o\": \"149.0385\",\n    \"t\": \"Nov 21, 2017 6:55:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.045\",\n    \"l\": \"149.034\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 6:56:00 AM\"\n  },\n  {\n    \"c\": \"149.0245\",\n    \"h\": \"149.0425\",\n    \"l\": \"149.022\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 6:57:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.037\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 6:58:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.0285\",\n    \"l\": \"149.015\",\n    \"o\": \"149.0285\",\n    \"t\": \"Nov 21, 2017 6:59:00 AM\"\n  },\n  {\n    \"c\": \"149.032\",\n    \"h\": \"149.033\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 7:00:00 AM\"\n  },\n  {\n    \"c\": \"149.025\",\n    \"h\": \"149.035\",\n    \"l\": \"149.022\",\n    \"o\": \"149.031\",\n    \"t\": \"Nov 21, 2017 7:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0245\",\n    \"h\": \"149.029\",\n    \"l\": \"149.011\",\n    \"o\": \"149.0245\",\n    \"t\": \"Nov 21, 2017 7:02:00 AM\"\n  },\n  {\n    \"c\": \"149.019\",\n    \"h\": \"149.029\",\n    \"l\": \"149.0135\",\n    \"o\": \"149.026\",\n    \"t\": \"Nov 21, 2017 7:03:00 AM\"\n  },\n  {\n    \"c\": \"149.011\",\n    \"h\": \"149.02\",\n    \"l\": \"149.011\",\n    \"o\": \"149.02\",\n    \"t\": \"Nov 21, 2017 7:04:00 AM\"\n  },\n  {\n    \"c\": \"149.0035\",\n    \"h\": \"149.0165\",\n    \"l\": \"148.9985\",\n    \"o\": \"149.012\",\n    \"t\": \"Nov 21, 2017 7:05:00 AM\"\n  },\n  {\n    \"c\": \"149.012\",\n    \"h\": \"149.012\",\n    \"l\": \"148.9965\",\n    \"o\": \"149.0045\",\n    \"t\": \"Nov 21, 2017 7:06:00 AM\"\n  },\n  {\n    \"c\": \"148.989\",\n    \"h\": \"149.014\",\n    \"l\": \"148.987\",\n    \"o\": \"149.0115\",\n    \"t\": \"Nov 21, 2017 7:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0215\",\n    \"h\": \"149.0225\",\n    \"l\": \"148.991\",\n    \"o\": \"148.991\",\n    \"t\": \"Nov 21, 2017 7:08:00 AM\"\n  },\n  {\n    \"c\": \"149.0195\",\n    \"h\": \"149.024\",\n    \"l\": \"149.019\",\n    \"o\": \"149.019\",\n    \"t\": \"Nov 21, 2017 7:09:00 AM\"\n  },\n  {\n    \"c\": \"149.024\",\n    \"h\": \"149.0255\",\n    \"l\": \"149.017\",\n    \"o\": \"149.018\",\n    \"t\": \"Nov 21, 2017 7:10:00 AM\"\n  },\n  {\n    \"c\": \"149.052\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.02\",\n    \"o\": \"149.0225\",\n    \"t\": \"Nov 21, 2017 7:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0485\",\n    \"h\": \"149.0545\",\n    \"l\": \"149.048\",\n    \"o\": \"149.052\",\n    \"t\": \"Nov 21, 2017 7:12:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.048\",\n    \"l\": \"149.041\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:13:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.043\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.043\",\n    \"t\": \"Nov 21, 2017 7:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0335\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.0305\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 7:15:00 AM\"\n  },\n  {\n    \"c\": \"149.0285\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.027\",\n    \"o\": \"149.0325\",\n    \"t\": \"Nov 21, 2017 7:16:00 AM\"\n  },\n  {\n    \"c\": \"149.027\",\n    \"h\": \"149.03\",\n    \"l\": \"149.0225\",\n    \"o\": \"149.0285\",\n    \"t\": \"Nov 21, 2017 7:17:00 AM\"\n  },\n  {\n    \"c\": \"149.0295\",\n    \"h\": \"149.03\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0265\",\n    \"t\": \"Nov 21, 2017 7:18:00 AM\"\n  },\n  {\n    \"c\": \"149.031\",\n    \"h\": \"149.031\",\n    \"l\": \"149.027\",\n    \"o\": \"149.0295\",\n    \"t\": \"Nov 21, 2017 7:19:00 AM\"\n  },\n  {\n    \"c\": \"149.028\",\n    \"h\": \"149.031\",\n    \"l\": \"149.028\",\n    \"o\": \"149.029\",\n    \"t\": \"Nov 21, 2017 7:20:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.0375\",\n    \"l\": \"149.0265\",\n    \"o\": \"149.027\",\n    \"t\": \"Nov 21, 2017 7:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.043\",\n    \"l\": \"149.0325\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 7:22:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.037\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.037\",\n    \"t\": \"Nov 21, 2017 7:23:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.033\",\n    \"o\": \"149.033\",\n    \"t\": \"Nov 21, 2017 7:24:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.03\",\n    \"o\": \"149.033\",\n    \"t\": \"Nov 21, 2017 7:25:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0345\",\n    \"l\": \"149.033\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 7:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0435\",\n    \"l\": \"149.032\",\n    \"o\": \"149.0325\",\n    \"t\": \"Nov 21, 2017 7:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0465\",\n    \"h\": \"149.05\",\n    \"l\": \"149.0425\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:28:00 AM\"\n  },\n  {\n    \"c\": \"149.0475\",\n    \"h\": \"149.0485\",\n    \"l\": \"149.0465\",\n    \"o\": \"149.047\",\n    \"t\": \"Nov 21, 2017 7:29:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0595\",\n    \"l\": \"149.048\",\n    \"o\": \"149.048\",\n    \"t\": \"Nov 21, 2017 7:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0595\",\n    \"h\": \"149.06\",\n    \"l\": \"149.057\",\n    \"o\": \"149.057\",\n    \"t\": \"Nov 21, 2017 7:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0605\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.056\",\n    \"o\": \"149.058\",\n    \"t\": \"Nov 21, 2017 7:32:00 AM\"\n  },\n  {\n    \"c\": \"149.067\",\n    \"h\": \"149.07\",\n    \"l\": \"149.059\",\n    \"o\": \"149.062\",\n    \"t\": \"Nov 21, 2017 7:33:00 AM\"\n  },\n  {\n    \"c\": \"149.063\",\n    \"h\": \"149.075\",\n    \"l\": \"149.063\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 7:34:00 AM\"\n  },\n  {\n    \"c\": \"149.062\",\n    \"h\": \"149.065\",\n    \"l\": \"149.0615\",\n    \"o\": \"149.0635\",\n    \"t\": \"Nov 21, 2017 7:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.063\",\n    \"l\": \"149.061\",\n    \"o\": \"149.061\",\n    \"t\": \"Nov 21, 2017 7:36:00 AM\"\n  },\n  {\n    \"c\": \"149.06\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.056\",\n    \"o\": \"149.062\",\n    \"t\": \"Nov 21, 2017 7:37:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.085\",\n    \"l\": \"149.059\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 7:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.085\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 7:39:00 AM\"\n  },\n  {\n    \"c\": \"149.0705\",\n    \"h\": \"149.0735\",\n    \"l\": \"149.0685\",\n    \"o\": \"149.073\",\n    \"t\": \"Nov 21, 2017 7:40:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.074\",\n    \"l\": \"149.0635\",\n    \"o\": \"149.07\",\n    \"t\": \"Nov 21, 2017 7:41:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.077\",\n    \"l\": \"149.058\",\n    \"o\": \"149.0665\",\n    \"t\": \"Nov 21, 2017 7:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0705\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.066\",\n    \"o\": \"149.077\",\n    \"t\": \"Nov 21, 2017 7:43:00 AM\"\n  },\n  {\n    \"c\": \"149.059\",\n    \"h\": \"149.0775\",\n    \"l\": \"149.058\",\n    \"o\": \"149.071\",\n    \"t\": \"Nov 21, 2017 7:44:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.08\",\n    \"l\": \"149.052\",\n    \"o\": \"149.0595\",\n    \"t\": \"Nov 21, 2017 7:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0605\",\n    \"h\": \"149.077\",\n    \"l\": \"149.0605\",\n    \"o\": \"149.0765\",\n    \"t\": \"Nov 21, 2017 7:46:00 AM\"\n  },\n  {\n    \"c\": \"149.044\",\n    \"h\": \"149.0605\",\n    \"l\": \"149.038\",\n    \"o\": \"149.06\",\n    \"t\": \"Nov 21, 2017 7:47:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.063\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:48:00 AM\"\n  },\n  {\n    \"c\": \"149.06\",\n    \"h\": \"149.06\",\n    \"l\": \"149.048\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 7:49:00 AM\"\n  },\n  {\n    \"c\": \"149.058\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.0565\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 7:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0555\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.0555\",\n    \"o\": \"149.058\",\n    \"t\": \"Nov 21, 2017 7:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0125\",\n    \"h\": \"149.056\",\n    \"l\": \"149.0125\",\n    \"o\": \"149.054\",\n    \"t\": \"Nov 21, 2017 7:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0165\",\n    \"h\": \"149.02\",\n    \"l\": \"149.0015\",\n    \"o\": \"149.0135\",\n    \"t\": \"Nov 21, 2017 7:53:00 AM\"\n  },\n  {\n    \"c\": \"149.026\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.007\",\n    \"o\": \"149.0145\",\n    \"t\": \"Nov 21, 2017 7:54:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.0355\",\n    \"l\": \"149.0235\",\n    \"o\": \"149.0255\",\n    \"t\": \"Nov 21, 2017 7:55:00 AM\"\n  },\n  {\n    \"c\": \"149.036\",\n    \"h\": \"149.0495\",\n    \"l\": \"149.0305\",\n    \"o\": \"149.0305\",\n    \"t\": \"Nov 21, 2017 7:56:00 AM\"\n  },\n  {\n    \"c\": \"149.041\",\n    \"h\": \"149.042\",\n    \"l\": \"149.036\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 7:57:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.0405\",\n    \"o\": \"149.042\",\n    \"t\": \"Nov 21, 2017 7:58:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.052\",\n    \"l\": \"149.043\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 7:59:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.0565\",\n    \"l\": \"149.032\",\n    \"o\": \"149.047\",\n    \"t\": \"Nov 21, 2017 8:00:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.096\",\n    \"l\": \"149.036\",\n    \"o\": \"149.0425\",\n    \"t\": \"Nov 21, 2017 8:01:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.104\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 8:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1095\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.083\",\n    \"o\": \"149.104\",\n    \"t\": \"Nov 21, 2017 8:03:00 AM\"\n  },\n  {\n    \"c\": \"149.126\",\n    \"h\": \"149.1395\",\n    \"l\": \"149.109\",\n    \"o\": \"149.11\",\n    \"t\": \"Nov 21, 2017 8:04:00 AM\"\n  },\n  {\n    \"c\": \"149.127\",\n    \"h\": \"149.141\",\n    \"l\": \"149.123\",\n    \"o\": \"149.1255\",\n    \"t\": \"Nov 21, 2017 8:05:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.138\",\n    \"l\": \"149.112\",\n    \"o\": \"149.126\",\n    \"t\": \"Nov 21, 2017 8:06:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.1185\",\n    \"l\": \"149.078\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 8:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0825\",\n    \"h\": \"149.0875\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 8:08:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.0665\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 8:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0545\",\n    \"h\": \"149.076\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.0745\",\n    \"t\": \"Nov 21, 2017 8:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0685\",\n    \"h\": \"149.0695\",\n    \"l\": \"149.0525\",\n    \"o\": \"149.053\",\n    \"t\": \"Nov 21, 2017 8:11:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.1025\",\n    \"l\": \"149.063\",\n    \"o\": \"149.068\",\n    \"t\": \"Nov 21, 2017 8:12:00 AM\"\n  },\n  {\n    \"c\": \"149.116\",\n    \"h\": \"149.1195\",\n    \"l\": \"149.0935\",\n    \"o\": \"149.0935\",\n    \"t\": \"Nov 21, 2017 8:13:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.103\",\n    \"o\": \"149.1155\",\n    \"t\": \"Nov 21, 2017 8:14:00 AM\"\n  },\n  {\n    \"c\": \"149.1065\",\n    \"h\": \"149.124\",\n    \"l\": \"149.099\",\n    \"o\": \"149.1025\",\n    \"t\": \"Nov 21, 2017 8:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1125\",\n    \"h\": \"149.1135\",\n    \"l\": \"149.1005\",\n    \"o\": \"149.1075\",\n    \"t\": \"Nov 21, 2017 8:16:00 AM\"\n  },\n  {\n    \"c\": \"149.1295\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1125\",\n    \"o\": \"149.1125\",\n    \"t\": \"Nov 21, 2017 8:17:00 AM\"\n  },\n  {\n    \"c\": \"149.135\",\n    \"h\": \"149.1375\",\n    \"l\": \"149.1225\",\n    \"o\": \"149.1285\",\n    \"t\": \"Nov 21, 2017 8:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.1395\",\n    \"l\": \"149.1325\",\n    \"o\": \"149.135\",\n    \"t\": \"Nov 21, 2017 8:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1615\",\n    \"h\": \"149.17\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1375\",\n    \"t\": \"Nov 21, 2017 8:20:00 AM\"\n  },\n  {\n    \"c\": \"149.1415\",\n    \"h\": \"149.173\",\n    \"l\": \"149.141\",\n    \"o\": \"149.162\",\n    \"t\": \"Nov 21, 2017 8:21:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.153\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1425\",\n    \"t\": \"Nov 21, 2017 8:22:00 AM\"\n  },\n  {\n    \"c\": \"149.131\",\n    \"h\": \"149.1465\",\n    \"l\": \"149.126\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 8:23:00 AM\"\n  },\n  {\n    \"c\": \"149.1325\",\n    \"h\": \"149.1365\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 8:24:00 AM\"\n  },\n  {\n    \"c\": \"149.1565\",\n    \"h\": \"149.157\",\n    \"l\": \"149.1335\",\n    \"o\": \"149.1335\",\n    \"t\": \"Nov 21, 2017 8:25:00 AM\"\n  },\n  {\n    \"c\": \"149.208\",\n    \"h\": \"149.21\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1555\",\n    \"t\": \"Nov 21, 2017 8:26:00 AM\"\n  },\n  {\n    \"c\": \"149.198\",\n    \"h\": \"149.218\",\n    \"l\": \"149.1915\",\n    \"o\": \"149.207\",\n    \"t\": \"Nov 21, 2017 8:27:00 AM\"\n  },\n  {\n    \"c\": \"149.202\",\n    \"h\": \"149.207\",\n    \"l\": \"149.195\",\n    \"o\": \"149.196\",\n    \"t\": \"Nov 21, 2017 8:28:00 AM\"\n  },\n  {\n    \"c\": \"149.216\",\n    \"h\": \"149.2235\",\n    \"l\": \"149.191\",\n    \"o\": \"149.2035\",\n    \"t\": \"Nov 21, 2017 8:29:00 AM\"\n  },\n  {\n    \"c\": \"149.193\",\n    \"h\": \"149.216\",\n    \"l\": \"149.185\",\n    \"o\": \"149.2145\",\n    \"t\": \"Nov 21, 2017 8:30:00 AM\"\n  },\n  {\n    \"c\": \"149.1835\",\n    \"h\": \"149.197\",\n    \"l\": \"149.1835\",\n    \"o\": \"149.193\",\n    \"t\": \"Nov 21, 2017 8:31:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1905\",\n    \"l\": \"149.1735\",\n    \"o\": \"149.182\",\n    \"t\": \"Nov 21, 2017 8:32:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1835\",\n    \"l\": \"149.1705\",\n    \"o\": \"149.174\",\n    \"t\": \"Nov 21, 2017 8:33:00 AM\"\n  },\n  {\n    \"c\": \"149.1795\",\n    \"h\": \"149.187\",\n    \"l\": \"149.1715\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:34:00 AM\"\n  },\n  {\n    \"c\": \"149.2055\",\n    \"h\": \"149.209\",\n    \"l\": \"149.1805\",\n    \"o\": \"149.1805\",\n    \"t\": \"Nov 21, 2017 8:35:00 AM\"\n  },\n  {\n    \"c\": \"149.194\",\n    \"h\": \"149.2095\",\n    \"l\": \"149.1925\",\n    \"o\": \"149.2055\",\n    \"t\": \"Nov 21, 2017 8:36:00 AM\"\n  },\n  {\n    \"c\": \"149.1955\",\n    \"h\": \"149.2\",\n    \"l\": \"149.1845\",\n    \"o\": \"149.1935\",\n    \"t\": \"Nov 21, 2017 8:37:00 AM\"\n  },\n  {\n    \"c\": \"149.1995\",\n    \"h\": \"149.211\",\n    \"l\": \"149.184\",\n    \"o\": \"149.194\",\n    \"t\": \"Nov 21, 2017 8:38:00 AM\"\n  },\n  {\n    \"c\": \"149.202\",\n    \"h\": \"149.206\",\n    \"l\": \"149.1905\",\n    \"o\": \"149.199\",\n    \"t\": \"Nov 21, 2017 8:39:00 AM\"\n  },\n  {\n    \"c\": \"149.184\",\n    \"h\": \"149.2025\",\n    \"l\": \"149.17\",\n    \"o\": \"149.202\",\n    \"t\": \"Nov 21, 2017 8:40:00 AM\"\n  },\n  {\n    \"c\": \"149.187\",\n    \"h\": \"149.1945\",\n    \"l\": \"149.174\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 8:41:00 AM\"\n  }\n]"
  },
  {
    "path": "app/src/main/assets/timesharing2.json",
    "content": "[\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:42:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:43:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:45:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:46:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:48:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:42:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:43:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:45:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:46:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:48:00 AM\"\n  }\n]"
  },
  {
    "path": "app/src/main/assets/timesharing22.json",
    "content": "[\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1865\",\n    \"t\": \"Nov 21, 2017 8:42:00 AM\"\n  },\n  {\n    \"c\": \"149.146\",\n    \"h\": \"149.177\",\n    \"l\": \"149.146\",\n    \"o\": \"149.176\",\n    \"t\": \"Nov 21, 2017 8:43:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.1615\",\n    \"l\": \"149.1395\",\n    \"o\": \"149.1455\",\n    \"t\": \"Nov 21, 2017 8:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1605\",\n    \"h\": \"149.162\",\n    \"l\": \"149.1405\",\n    \"o\": \"149.1445\",\n    \"t\": \"Nov 21, 2017 8:45:00 AM\"\n  },\n  {\n    \"c\": \"149.1515\",\n    \"h\": \"149.1605\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.1605\",\n    \"t\": \"Nov 21, 2017 8:46:00 AM\"\n  },\n  {\n    \"c\": \"149.1515\",\n    \"h\": \"149.152\",\n    \"l\": \"149.144\",\n    \"o\": \"149.151\",\n    \"t\": \"Nov 21, 2017 8:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.1735\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.151\",\n    \"t\": \"Nov 21, 2017 8:48:00 AM\"\n  },\n  {\n    \"c\": \"149.1675\",\n    \"h\": \"149.177\",\n    \"l\": \"149.1565\",\n    \"o\": \"149.166\",\n    \"t\": \"Nov 21, 2017 8:49:00 AM\"\n  },\n  {\n    \"c\": \"149.175\",\n    \"h\": \"149.185\",\n    \"l\": \"149.1655\",\n    \"o\": \"149.1675\",\n    \"t\": \"Nov 21, 2017 8:50:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.1825\",\n    \"l\": \"149.159\",\n    \"o\": \"149.174\",\n    \"t\": \"Nov 21, 2017 8:51:00 AM\"\n  },\n  {\n    \"c\": \"149.184\",\n    \"h\": \"149.1845\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 8:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1815\",\n    \"h\": \"149.1845\",\n    \"l\": \"149.164\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 8:53:00 AM\"\n  },\n  {\n    \"c\": \"149.1575\",\n    \"h\": \"149.2005\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.182\",\n    \"t\": \"Nov 21, 2017 8:54:00 AM\"\n  },\n  {\n    \"c\": \"149.197\",\n    \"h\": \"149.198\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1585\",\n    \"t\": \"Nov 21, 2017 8:55:00 AM\"\n  },\n  {\n    \"c\": \"149.189\",\n    \"h\": \"149.198\",\n    \"l\": \"149.185\",\n    \"o\": \"149.1945\",\n    \"t\": \"Nov 21, 2017 8:56:00 AM\"\n  },\n  {\n    \"c\": \"149.18\",\n    \"h\": \"149.1895\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.1895\",\n    \"t\": \"Nov 21, 2017 8:57:00 AM\"\n  },\n  {\n    \"c\": \"149.158\",\n    \"h\": \"149.1785\",\n    \"l\": \"149.1505\",\n    \"o\": \"149.1785\",\n    \"t\": \"Nov 21, 2017 8:58:00 AM\"\n  },\n  {\n    \"c\": \"149.139\",\n    \"h\": \"149.1575\",\n    \"l\": \"149.128\",\n    \"o\": \"149.157\",\n    \"t\": \"Nov 21, 2017 8:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1095\",\n    \"h\": \"149.1385\",\n    \"l\": \"149.108\",\n    \"o\": \"149.1375\",\n    \"t\": \"Nov 21, 2017 9:00:00 AM\"\n  },\n  {\n    \"c\": \"149.1035\",\n    \"h\": \"149.1095\",\n    \"l\": \"149.098\",\n    \"o\": \"149.1095\",\n    \"t\": \"Nov 21, 2017 9:01:00 AM\"\n  },\n  {\n    \"c\": \"149.113\",\n    \"h\": \"149.113\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.1035\",\n    \"t\": \"Nov 21, 2017 9:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.1225\",\n    \"l\": \"149.1075\",\n    \"o\": \"149.1125\",\n    \"t\": \"Nov 21, 2017 9:03:00 AM\"\n  },\n  {\n    \"c\": \"149.1225\",\n    \"h\": \"149.1375\",\n    \"l\": \"149.114\",\n    \"o\": \"149.1145\",\n    \"t\": \"Nov 21, 2017 9:04:00 AM\"\n  },\n  {\n    \"c\": \"149.134\",\n    \"h\": \"149.1365\",\n    \"l\": \"149.118\",\n    \"o\": \"149.1235\",\n    \"t\": \"Nov 21, 2017 9:05:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.0975\",\n    \"o\": \"149.1345\",\n    \"t\": \"Nov 21, 2017 9:06:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.11\",\n    \"l\": \"149.1015\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 9:07:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.1045\",\n    \"l\": \"149.084\",\n    \"o\": \"149.1045\",\n    \"t\": \"Nov 21, 2017 9:08:00 AM\"\n  },\n  {\n    \"c\": \"149.092\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.088\",\n    \"o\": \"149.093\",\n    \"t\": \"Nov 21, 2017 9:09:00 AM\"\n  },\n  {\n    \"c\": \"149.071\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0615\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 9:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.064\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 9:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.0905\",\n    \"t\": \"Nov 21, 2017 9:12:00 AM\"\n  },\n  {\n    \"c\": \"149.1175\",\n    \"h\": \"149.122\",\n    \"l\": \"149.0895\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 9:13:00 AM\"\n  },\n  {\n    \"c\": \"149.133\",\n    \"h\": \"149.135\",\n    \"l\": \"149.1165\",\n    \"o\": \"149.1165\",\n    \"t\": \"Nov 21, 2017 9:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0975\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.0975\",\n    \"o\": \"149.1325\",\n    \"t\": \"Nov 21, 2017 9:15:00 AM\"\n  },\n  {\n    \"c\": \"149.098\",\n    \"h\": \"149.111\",\n    \"l\": \"149.091\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 9:16:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.106\",\n    \"l\": \"149.078\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 9:17:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.081\",\n    \"o\": \"149.0905\",\n    \"t\": \"Nov 21, 2017 9:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.09\",\n    \"l\": \"149.081\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 9:19:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.091\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0885\",\n    \"t\": \"Nov 21, 2017 9:20:00 AM\"\n  },\n  {\n    \"c\": \"149.094\",\n    \"h\": \"149.0995\",\n    \"l\": \"149.0755\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 9:21:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.0785\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 9:22:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.092\",\n    \"l\": \"149.075\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 9:23:00 AM\"\n  },\n  {\n    \"c\": \"149.0825\",\n    \"h\": \"149.0935\",\n    \"l\": \"149.074\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 9:24:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.082\",\n    \"l\": \"149.057\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 9:25:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.0745\",\n    \"l\": \"149.0395\",\n    \"o\": \"149.074\",\n    \"t\": \"Nov 21, 2017 9:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0145\",\n    \"h\": \"149.041\",\n    \"l\": \"149.012\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 9:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0085\",\n    \"h\": \"149.0235\",\n    \"l\": \"149.0065\",\n    \"o\": \"149.014\",\n    \"t\": \"Nov 21, 2017 9:28:00 AM\"\n  },\n  {\n    \"c\": \"149.0095\",\n    \"h\": \"149.0205\",\n    \"l\": \"149.005\",\n    \"o\": \"149.0095\",\n    \"t\": \"Nov 21, 2017 9:29:00 AM\"\n  },\n  {\n    \"c\": \"149.024\",\n    \"h\": \"149.05\",\n    \"l\": \"149.008\",\n    \"o\": \"149.008\",\n    \"t\": \"Nov 21, 2017 9:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0105\",\n    \"h\": \"149.0235\",\n    \"l\": \"148.9925\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 9:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.045\",\n    \"l\": \"149.01\",\n    \"o\": \"149.01\",\n    \"t\": \"Nov 21, 2017 9:32:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.045\",\n    \"l\": \"149.0295\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 9:33:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.0515\",\n    \"l\": \"149.03\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 9:34:00 AM\"\n  },\n  {\n    \"c\": \"149.05\",\n    \"h\": \"149.053\",\n    \"l\": \"149.038\",\n    \"o\": \"149.049\",\n    \"t\": \"Nov 21, 2017 9:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.056\",\n    \"l\": \"149.0465\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 9:36:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.054\",\n    \"l\": \"149.0415\",\n    \"o\": \"149.05\",\n    \"t\": \"Nov 21, 2017 9:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.071\",\n    \"l\": \"149.045\",\n    \"o\": \"149.051\",\n    \"t\": \"Nov 21, 2017 9:38:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.066\",\n    \"l\": \"149.051\",\n    \"o\": \"149.0515\",\n    \"t\": \"Nov 21, 2017 9:39:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.0695\",\n    \"l\": \"149.056\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 9:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0595\",\n    \"h\": \"149.0815\",\n    \"l\": \"149.0595\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 9:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.059\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 9:42:00 AM\"\n  },\n  {\n    \"c\": \"149.1075\",\n    \"h\": \"149.11\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 9:43:00 AM\"\n  },\n  {\n    \"c\": \"149.1035\",\n    \"h\": \"149.112\",\n    \"l\": \"149.0945\",\n    \"o\": \"149.108\",\n    \"t\": \"Nov 21, 2017 9:44:00 AM\"\n  },\n  {\n    \"c\": \"149.109\",\n    \"h\": \"149.1125\",\n    \"l\": \"149.0985\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 9:45:00 AM\"\n  },\n  {\n    \"c\": \"149.12\",\n    \"h\": \"149.121\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.1105\",\n    \"t\": \"Nov 21, 2017 9:46:00 AM\"\n  },\n  {\n    \"c\": \"149.1445\",\n    \"h\": \"149.1485\",\n    \"l\": \"149.1185\",\n    \"o\": \"149.12\",\n    \"t\": \"Nov 21, 2017 9:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.158\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 9:48:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.157\",\n    \"l\": \"149.138\",\n    \"o\": \"149.145\",\n    \"t\": \"Nov 21, 2017 9:49:00 AM\"\n  },\n  {\n    \"c\": \"149.1275\",\n    \"h\": \"149.152\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 9:50:00 AM\"\n  },\n  {\n    \"c\": \"149.119\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1275\",\n    \"t\": \"Nov 21, 2017 9:51:00 AM\"\n  },\n  {\n    \"c\": \"149.102\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.101\",\n    \"o\": \"149.1175\",\n    \"t\": \"Nov 21, 2017 9:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1175\",\n    \"h\": \"149.1175\",\n    \"l\": \"149.097\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 9:53:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.1175\",\n    \"l\": \"149.108\",\n    \"o\": \"149.117\",\n    \"t\": \"Nov 21, 2017 9:54:00 AM\"\n  },\n  {\n    \"c\": \"149.13\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.1155\",\n    \"t\": \"Nov 21, 2017 9:55:00 AM\"\n  },\n  {\n    \"c\": \"149.1335\",\n    \"h\": \"149.134\",\n    \"l\": \"149.121\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 9:56:00 AM\"\n  },\n  {\n    \"c\": \"149.1305\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.128\",\n    \"o\": \"149.1345\",\n    \"t\": \"Nov 21, 2017 9:57:00 AM\"\n  },\n  {\n    \"c\": \"149.1275\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 9:58:00 AM\"\n  },\n  {\n    \"c\": \"149.1255\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.1205\",\n    \"o\": \"149.128\",\n    \"t\": \"Nov 21, 2017 9:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1285\",\n    \"h\": \"149.1285\",\n    \"l\": \"149.115\",\n    \"o\": \"149.124\",\n    \"t\": \"Nov 21, 2017 10:00:00 AM\"\n  },\n  {\n    \"c\": \"149.121\",\n    \"h\": \"149.13\",\n    \"l\": \"149.1205\",\n    \"o\": \"149.1285\",\n    \"t\": \"Nov 21, 2017 10:01:00 AM\"\n  },\n  {\n    \"c\": \"149.135\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1195\",\n    \"o\": \"149.121\",\n    \"t\": \"Nov 21, 2017 10:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1355\",\n    \"h\": \"149.1415\",\n    \"l\": \"149.1315\",\n    \"o\": \"149.135\",\n    \"t\": \"Nov 21, 2017 10:03:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.156\",\n    \"l\": \"149.136\",\n    \"o\": \"149.136\",\n    \"t\": \"Nov 21, 2017 10:04:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.17\",\n    \"l\": \"149.1365\",\n    \"o\": \"149.144\",\n    \"t\": \"Nov 21, 2017 10:05:00 AM\"\n  },\n  {\n    \"c\": \"149.2005\",\n    \"h\": \"149.2005\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1585\",\n    \"t\": \"Nov 21, 2017 10:06:00 AM\"\n  },\n  {\n    \"c\": \"149.187\",\n    \"h\": \"149.202\",\n    \"l\": \"149.1865\",\n    \"o\": \"149.2005\",\n    \"t\": \"Nov 21, 2017 10:07:00 AM\"\n  },\n  {\n    \"c\": \"149.163\",\n    \"h\": \"149.188\",\n    \"l\": \"149.1605\",\n    \"o\": \"149.188\",\n    \"t\": \"Nov 21, 2017 10:08:00 AM\"\n  },\n  {\n    \"c\": \"149.152\",\n    \"h\": \"149.175\",\n    \"l\": \"149.147\",\n    \"o\": \"149.1635\",\n    \"t\": \"Nov 21, 2017 10:09:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1445\",\n    \"o\": \"149.1515\",\n    \"t\": \"Nov 21, 2017 10:10:00 AM\"\n  },\n  {\n    \"c\": \"149.1665\",\n    \"h\": \"149.1715\",\n    \"l\": \"149.148\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 10:11:00 AM\"\n  },\n  {\n    \"c\": \"149.182\",\n    \"h\": \"149.1885\",\n    \"l\": \"149.1645\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 10:12:00 AM\"\n  },\n  {\n    \"c\": \"149.1855\",\n    \"h\": \"149.187\",\n    \"l\": \"149.178\",\n    \"o\": \"149.1825\",\n    \"t\": \"Nov 21, 2017 10:13:00 AM\"\n  },\n  {\n    \"c\": \"149.1825\",\n    \"h\": \"149.1915\",\n    \"l\": \"149.18\",\n    \"o\": \"149.1855\",\n    \"t\": \"Nov 21, 2017 10:14:00 AM\"\n  },\n  {\n    \"c\": \"149.1685\",\n    \"h\": \"149.184\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 10:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.174\",\n    \"l\": \"149.159\",\n    \"o\": \"149.167\",\n    \"t\": \"Nov 21, 2017 10:16:00 AM\"\n  },\n  {\n    \"c\": \"149.167\",\n    \"h\": \"149.176\",\n    \"l\": \"149.1645\",\n    \"o\": \"149.166\",\n    \"t\": \"Nov 21, 2017 10:17:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1665\",\n    \"o\": \"149.167\",\n    \"t\": \"Nov 21, 2017 10:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1895\",\n    \"h\": \"149.202\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.176\",\n    \"t\": \"Nov 21, 2017 10:19:00 AM\"\n  },\n  {\n    \"c\": \"149.206\",\n    \"h\": \"149.208\",\n    \"l\": \"149.188\",\n    \"o\": \"149.1895\",\n    \"t\": \"Nov 21, 2017 10:20:00 AM\"\n  },\n  {\n    \"c\": \"149.198\",\n    \"h\": \"149.214\",\n    \"l\": \"149.1975\",\n    \"o\": \"149.2065\",\n    \"t\": \"Nov 21, 2017 10:21:00 AM\"\n  },\n  {\n    \"c\": \"149.1635\",\n    \"h\": \"149.1985\",\n    \"l\": \"149.1615\",\n    \"o\": \"149.1975\",\n    \"t\": \"Nov 21, 2017 10:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1685\",\n    \"h\": \"149.1725\",\n    \"l\": \"149.1595\",\n    \"o\": \"149.1625\",\n    \"t\": \"Nov 21, 2017 10:23:00 AM\"\n  },\n  {\n    \"c\": \"149.1665\",\n    \"h\": \"149.174\",\n    \"l\": \"149.163\",\n    \"o\": \"149.168\",\n    \"t\": \"Nov 21, 2017 10:24:00 AM\"\n  },\n  {\n    \"c\": \"149.161\",\n    \"h\": \"149.1725\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1665\",\n    \"t\": \"Nov 21, 2017 10:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1495\",\n    \"h\": \"149.1655\",\n    \"l\": \"149.146\",\n    \"o\": \"149.1615\",\n    \"t\": \"Nov 21, 2017 10:26:00 AM\"\n  },\n  {\n    \"c\": \"149.139\",\n    \"h\": \"149.1645\",\n    \"l\": \"149.139\",\n    \"o\": \"149.1495\",\n    \"t\": \"Nov 21, 2017 10:27:00 AM\"\n  },\n  {\n    \"c\": \"149.099\",\n    \"h\": \"149.139\",\n    \"l\": \"149.088\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 10:28:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.101\",\n    \"l\": \"149.089\",\n    \"o\": \"149.0995\",\n    \"t\": \"Nov 21, 2017 10:29:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.097\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.09\",\n    \"t\": \"Nov 21, 2017 10:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0995\",\n    \"h\": \"149.1055\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 10:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0865\",\n    \"h\": \"149.1035\",\n    \"l\": \"149.086\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 10:32:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 10:33:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.089\",\n    \"l\": \"149.048\",\n    \"o\": \"149.0845\",\n    \"t\": \"Nov 21, 2017 10:34:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.0685\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 10:35:00 AM\"\n  },\n  {\n    \"c\": \"149.068\",\n    \"h\": \"149.068\",\n    \"l\": \"149.0425\",\n    \"o\": \"149.05\",\n    \"t\": \"Nov 21, 2017 10:36:00 AM\"\n  },\n  {\n    \"c\": \"149.0545\",\n    \"h\": \"149.0765\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 10:37:00 AM\"\n  },\n  {\n    \"c\": \"149.081\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 10:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.084\",\n    \"l\": \"149.0685\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 10:39:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0695\",\n    \"o\": \"149.072\",\n    \"t\": \"Nov 21, 2017 10:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.091\",\n    \"t\": \"Nov 21, 2017 10:41:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.095\",\n    \"l\": \"149.077\",\n    \"o\": \"149.0805\",\n    \"t\": \"Nov 21, 2017 10:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0835\",\n    \"h\": \"149.096\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 10:43:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.091\",\n    \"l\": \"149.077\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 10:44:00 AM\"\n  },\n  {\n    \"c\": \"149.082\",\n    \"h\": \"149.089\",\n    \"l\": \"149.076\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 10:45:00 AM\"\n  },\n  {\n    \"c\": \"149.101\",\n    \"h\": \"149.104\",\n    \"l\": \"149.083\",\n    \"o\": \"149.084\",\n    \"t\": \"Nov 21, 2017 10:46:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.104\",\n    \"l\": \"149.083\",\n    \"o\": \"149.1\",\n    \"t\": \"Nov 21, 2017 10:47:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.092\",\n    \"l\": \"149.081\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:48:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.092\",\n    \"l\": \"149.08\",\n    \"o\": \"149.087\",\n    \"t\": \"Nov 21, 2017 10:49:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.088\",\n    \"l\": \"149.077\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 10:50:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.108\",\n    \"l\": \"149.077\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 10:51:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.111\",\n    \"l\": \"149.089\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 10:52:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.115\",\n    \"l\": \"149.093\",\n    \"o\": \"149.094\",\n    \"t\": \"Nov 21, 2017 10:53:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.117\",\n    \"l\": \"149.093\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 10:54:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.093\",\n    \"l\": \"149.08\",\n    \"o\": \"149.092\",\n    \"t\": \"Nov 21, 2017 10:55:00 AM\"\n  },\n  {\n    \"c\": \"149.073\",\n    \"h\": \"149.088\",\n    \"l\": \"149.064\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:56:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.087\",\n    \"l\": \"149.072\",\n    \"o\": \"149.072\",\n    \"t\": \"Nov 21, 2017 10:57:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.1\",\n    \"l\": \"149.082\",\n    \"o\": \"149.087\",\n    \"t\": \"Nov 21, 2017 10:58:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.086\",\n    \"l\": \"149.075\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:59:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.085\",\n    \"l\": \"149.07\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 11:00:00 AM\"\n  },\n  {\n    \"c\": \"149.082\",\n    \"h\": \"149.085\",\n    \"l\": \"149.073\",\n    \"o\": \"149.075\",\n    \"t\": \"Nov 21, 2017 11:01:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.097\",\n    \"l\": \"149.081\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 11:02:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.104\",\n    \"l\": \"149.08\",\n    \"o\": \"149.095\",\n    \"t\": \"Nov 21, 2017 11:03:00 AM\"\n  },\n  {\n    \"c\": \"149.081\",\n    \"h\": \"149.081\",\n    \"l\": \"149.079\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 11:04:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.081\",\n    \"l\": \"149.079\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 11:04:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.081\",\n    \"l\": \"149.079\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 11:04:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.081\",\n    \"l\": \"149.079\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 11:04:00 AM\"\n  }\n]"
  },
  {
    "path": "app/src/main/assets/timesharing3.json",
    "content": "[\n  {\n    \"c\": \"148.942\",\n    \"h\": \"148.9445\",\n    \"l\": \"148.9245\",\n    \"o\": \"148.926\",\n    \"t\": \"Nov 21, 2017 2:45:00 AM\"\n  },\n  {\n    \"c\": \"148.9105\",\n    \"h\": \"148.9445\",\n    \"l\": \"148.9075\",\n    \"o\": \"148.942\",\n    \"t\": \"Nov 21, 2017 2:46:00 AM\"\n  },\n  {\n    \"c\": \"148.9175\",\n    \"h\": \"148.9175\",\n    \"l\": \"148.878\",\n    \"o\": \"148.906\",\n    \"t\": \"Nov 21, 2017 2:47:00 AM\"\n  },\n  {\n    \"c\": \"148.9155\",\n    \"h\": \"148.933\",\n    \"l\": \"148.905\",\n    \"o\": \"148.9175\",\n    \"t\": \"Nov 21, 2017 2:48:00 AM\"\n  },\n  {\n    \"c\": \"148.9035\",\n    \"h\": \"148.9195\",\n    \"l\": \"148.8955\",\n    \"o\": \"148.916\",\n    \"t\": \"Nov 21, 2017 2:49:00 AM\"\n  },\n  {\n    \"c\": \"148.9045\",\n    \"h\": \"148.9075\",\n    \"l\": \"148.8975\",\n    \"o\": \"148.9035\",\n    \"t\": \"Nov 21, 2017 2:50:00 AM\"\n  },\n  {\n    \"c\": \"148.9\",\n    \"h\": \"148.9045\",\n    \"l\": \"148.9\",\n    \"o\": \"148.9045\",\n    \"t\": \"Nov 21, 2017 2:51:00 AM\"\n  },\n  {\n    \"c\": \"148.9025\",\n    \"h\": \"148.908\",\n    \"l\": \"148.8915\",\n    \"o\": \"148.9005\",\n    \"t\": \"Nov 21, 2017 2:52:00 AM\"\n  },\n  {\n    \"c\": \"148.926\",\n    \"h\": \"148.926\",\n    \"l\": \"148.9015\",\n    \"o\": \"148.9015\",\n    \"t\": \"Nov 21, 2017 2:53:00 AM\"\n  },\n  {\n    \"c\": \"148.9105\",\n    \"h\": \"148.926\",\n    \"l\": \"148.91\",\n    \"o\": \"148.926\",\n    \"t\": \"Nov 21, 2017 2:54:00 AM\"\n  },\n  {\n    \"c\": \"148.9265\",\n    \"h\": \"148.941\",\n    \"l\": \"148.91\",\n    \"o\": \"148.91\",\n    \"t\": \"Nov 21, 2017 2:55:00 AM\"\n  },\n  {\n    \"c\": \"148.933\",\n    \"h\": \"148.9455\",\n    \"l\": \"148.9255\",\n    \"o\": \"148.9265\",\n    \"t\": \"Nov 21, 2017 2:56:00 AM\"\n  },\n  {\n    \"c\": \"148.94\",\n    \"h\": \"148.952\",\n    \"l\": \"148.932\",\n    \"o\": \"148.9325\",\n    \"t\": \"Nov 21, 2017 2:57:00 AM\"\n  },\n  {\n    \"c\": \"148.9325\",\n    \"h\": \"148.9465\",\n    \"l\": \"148.928\",\n    \"o\": \"148.94\",\n    \"t\": \"Nov 21, 2017 2:58:00 AM\"\n  },\n  {\n    \"c\": \"148.937\",\n    \"h\": \"148.9395\",\n    \"l\": \"148.913\",\n    \"o\": \"148.932\",\n    \"t\": \"Nov 21, 2017 2:59:00 AM\"\n  },\n  {\n    \"c\": \"148.9635\",\n    \"h\": \"148.9655\",\n    \"l\": \"148.937\",\n    \"o\": \"148.937\",\n    \"t\": \"Nov 21, 2017 3:00:00 AM\"\n  },\n  {\n    \"c\": \"148.973\",\n    \"h\": \"148.978\",\n    \"l\": \"148.962\",\n    \"o\": \"148.962\",\n    \"t\": \"Nov 21, 2017 3:01:00 AM\"\n  },\n  {\n    \"c\": \"148.9725\",\n    \"h\": \"148.976\",\n    \"l\": \"148.966\",\n    \"o\": \"148.9725\",\n    \"t\": \"Nov 21, 2017 3:02:00 AM\"\n  },\n  {\n    \"c\": \"148.975\",\n    \"h\": \"148.975\",\n    \"l\": \"148.965\",\n    \"o\": \"148.9725\",\n    \"t\": \"Nov 21, 2017 3:03:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.03\",\n    \"l\": \"148.9635\",\n    \"o\": \"148.976\",\n    \"t\": \"Nov 21, 2017 3:04:00 AM\"\n  },\n  {\n    \"c\": \"148.972\",\n    \"h\": \"149.093\",\n    \"l\": \"148.9695\",\n    \"o\": \"149.024\",\n    \"t\": \"Nov 21, 2017 3:05:00 AM\"\n  },\n  {\n    \"c\": \"148.981\",\n    \"h\": \"148.981\",\n    \"l\": \"148.9615\",\n    \"o\": \"148.973\",\n    \"t\": \"Nov 21, 2017 3:06:00 AM\"\n  },\n  {\n    \"c\": \"148.9825\",\n    \"h\": \"148.9885\",\n    \"l\": \"148.9755\",\n    \"o\": \"148.981\",\n    \"t\": \"Nov 21, 2017 3:07:00 AM\"\n  },\n  {\n    \"c\": \"148.9695\",\n    \"h\": \"148.994\",\n    \"l\": \"148.9665\",\n    \"o\": \"148.982\",\n    \"t\": \"Nov 21, 2017 3:08:00 AM\"\n  },\n  {\n    \"c\": \"148.9675\",\n    \"h\": \"148.9815\",\n    \"l\": \"148.9635\",\n    \"o\": \"148.97\",\n    \"t\": \"Nov 21, 2017 3:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0195\",\n    \"h\": \"149.0215\",\n    \"l\": \"148.963\",\n    \"o\": \"148.9675\",\n    \"t\": \"Nov 21, 2017 3:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.0355\",\n    \"l\": \"149.005\",\n    \"o\": \"149.0185\",\n    \"t\": \"Nov 21, 2017 3:11:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.036\",\n    \"t\": \"Nov 21, 2017 3:12:00 AM\"\n  },\n  {\n    \"c\": \"149.02\",\n    \"h\": \"149.0315\",\n    \"l\": \"149.016\",\n    \"o\": \"149.0295\",\n    \"t\": \"Nov 21, 2017 3:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.071\",\n    \"l\": \"149.0195\",\n    \"o\": \"149.0215\",\n    \"t\": \"Nov 21, 2017 3:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0655\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.032\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 3:15:00 AM\"\n  },\n  {\n    \"c\": \"149.065\",\n    \"h\": \"149.0795\",\n    \"l\": \"149.059\",\n    \"o\": \"149.0655\",\n    \"t\": \"Nov 21, 2017 3:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.09\",\n    \"l\": \"149.062\",\n    \"o\": \"149.0645\",\n    \"t\": \"Nov 21, 2017 3:17:00 AM\"\n  },\n  {\n    \"c\": \"149.078\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.06\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 3:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.086\",\n    \"l\": \"149.0755\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 3:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1755\",\n    \"l\": \"149.085\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 3:20:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.178\",\n    \"l\": \"149.103\",\n    \"o\": \"149.1735\",\n    \"t\": \"Nov 21, 2017 3:21:00 AM\"\n  },\n  {\n    \"c\": \"149.1395\",\n    \"h\": \"149.149\",\n    \"l\": \"149.1255\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 3:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1385\",\n    \"t\": \"Nov 21, 2017 3:23:00 AM\"\n  },\n  {\n    \"c\": \"149.157\",\n    \"h\": \"149.1615\",\n    \"l\": \"149.1475\",\n    \"o\": \"149.1595\",\n    \"t\": \"Nov 21, 2017 3:24:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.158\",\n    \"l\": \"149.131\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 3:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.157\",\n    \"l\": \"149.145\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 3:26:00 AM\"\n  },\n  {\n    \"c\": \"149.165\",\n    \"h\": \"149.171\",\n    \"l\": \"149.1475\",\n    \"o\": \"149.1485\",\n    \"t\": \"Nov 21, 2017 3:27:00 AM\"\n  },\n  {\n    \"c\": \"149.178\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1635\",\n    \"t\": \"Nov 21, 2017 3:28:00 AM\"\n  },\n  {\n    \"c\": \"149.19\",\n    \"h\": \"149.19\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.178\",\n    \"t\": \"Nov 21, 2017 3:29:00 AM\"\n  },\n  {\n    \"c\": \"149.1835\",\n    \"h\": \"149.198\",\n    \"l\": \"149.177\",\n    \"o\": \"149.191\",\n    \"t\": \"Nov 21, 2017 3:30:00 AM\"\n  },\n  {\n    \"c\": \"149.177\",\n    \"h\": \"149.187\",\n    \"l\": \"149.167\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 3:31:00 AM\"\n  },\n  {\n    \"c\": \"149.1725\",\n    \"h\": \"149.1855\",\n    \"l\": \"149.1685\",\n    \"o\": \"149.1775\",\n    \"t\": \"Nov 21, 2017 3:32:00 AM\"\n  },\n  {\n    \"c\": \"149.193\",\n    \"h\": \"149.195\",\n    \"l\": \"149.168\",\n    \"o\": \"149.1725\",\n    \"t\": \"Nov 21, 2017 3:33:00 AM\"\n  },\n  {\n    \"c\": \"149.191\",\n    \"h\": \"149.204\",\n    \"l\": \"149.1825\",\n    \"o\": \"149.1935\",\n    \"t\": \"Nov 21, 2017 3:34:00 AM\"\n  },\n  {\n    \"c\": \"149.195\",\n    \"h\": \"149.198\",\n    \"l\": \"149.1825\",\n    \"o\": \"149.1905\",\n    \"t\": \"Nov 21, 2017 3:35:00 AM\"\n  },\n  {\n    \"c\": \"149.197\",\n    \"h\": \"149.2395\",\n    \"l\": \"149.193\",\n    \"o\": \"149.196\",\n    \"t\": \"Nov 21, 2017 3:36:00 AM\"\n  },\n  {\n    \"c\": \"149.2235\",\n    \"h\": \"149.232\",\n    \"l\": \"149.193\",\n    \"o\": \"149.197\",\n    \"t\": \"Nov 21, 2017 3:37:00 AM\"\n  },\n  {\n    \"c\": \"149.2065\",\n    \"h\": \"149.2355\",\n    \"l\": \"149.2065\",\n    \"o\": \"149.224\",\n    \"t\": \"Nov 21, 2017 3:38:00 AM\"\n  },\n  {\n    \"c\": \"149.2145\",\n    \"h\": \"149.2185\",\n    \"l\": \"149.2075\",\n    \"o\": \"149.2075\",\n    \"t\": \"Nov 21, 2017 3:39:00 AM\"\n  },\n  {\n    \"c\": \"149.2075\",\n    \"h\": \"149.2145\",\n    \"l\": \"149.2045\",\n    \"o\": \"149.2145\",\n    \"t\": \"Nov 21, 2017 3:40:00 AM\"\n  },\n  {\n    \"c\": \"149.1765\",\n    \"h\": \"149.2125\",\n    \"l\": \"149.1765\",\n    \"o\": \"149.2085\",\n    \"t\": \"Nov 21, 2017 3:41:00 AM\"\n  },\n  {\n    \"c\": \"149.171\",\n    \"h\": \"149.189\",\n    \"l\": \"149.1655\",\n    \"o\": \"149.1775\",\n    \"t\": \"Nov 21, 2017 3:42:00 AM\"\n  },\n  {\n    \"c\": \"149.183\",\n    \"h\": \"149.188\",\n    \"l\": \"149.165\",\n    \"o\": \"149.171\",\n    \"t\": \"Nov 21, 2017 3:43:00 AM\"\n  },\n  {\n    \"c\": \"149.181\",\n    \"h\": \"149.1925\",\n    \"l\": \"149.1685\",\n    \"o\": \"149.183\",\n    \"t\": \"Nov 21, 2017 3:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1775\",\n    \"h\": \"149.192\",\n    \"l\": \"149.172\",\n    \"o\": \"149.179\",\n    \"t\": \"Nov 21, 2017 3:45:00 AM\"\n  },\n  {\n    \"c\": \"149.174\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1765\",\n    \"t\": \"Nov 21, 2017 3:46:00 AM\"\n  },\n  {\n    \"c\": \"149.17\",\n    \"h\": \"149.1885\",\n    \"l\": \"149.17\",\n    \"o\": \"149.1745\",\n    \"t\": \"Nov 21, 2017 3:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.166\",\n    \"o\": \"149.1705\",\n    \"t\": \"Nov 21, 2017 3:48:00 AM\"\n  },\n  {\n    \"c\": \"149.1815\",\n    \"h\": \"149.1875\",\n    \"l\": \"149.1735\",\n    \"o\": \"149.1735\",\n    \"t\": \"Nov 21, 2017 3:49:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.181\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.1805\",\n    \"t\": \"Nov 21, 2017 3:50:00 AM\"\n  },\n  {\n    \"c\": \"149.1465\",\n    \"h\": \"149.162\",\n    \"l\": \"149.1455\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 3:51:00 AM\"\n  },\n  {\n    \"c\": \"149.1545\",\n    \"h\": \"149.1625\",\n    \"l\": \"149.141\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 3:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1405\",\n    \"h\": \"149.163\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1545\",\n    \"t\": \"Nov 21, 2017 3:53:00 AM\"\n  },\n  {\n    \"c\": \"149.148\",\n    \"h\": \"149.1505\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1405\",\n    \"t\": \"Nov 21, 2017 3:54:00 AM\"\n  },\n  {\n    \"c\": \"149.153\",\n    \"h\": \"149.156\",\n    \"l\": \"149.129\",\n    \"o\": \"149.148\",\n    \"t\": \"Nov 21, 2017 3:55:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.154\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1535\",\n    \"t\": \"Nov 21, 2017 3:56:00 AM\"\n  },\n  {\n    \"c\": \"149.163\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 3:57:00 AM\"\n  },\n  {\n    \"c\": \"149.166\",\n    \"h\": \"149.174\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.163\",\n    \"t\": \"Nov 21, 2017 3:58:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1435\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 3:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1245\",\n    \"h\": \"149.1515\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 4:00:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.1295\",\n    \"l\": \"149.115\",\n    \"o\": \"149.1245\",\n    \"t\": \"Nov 21, 2017 4:01:00 AM\"\n  },\n  {\n    \"c\": \"149.119\",\n    \"h\": \"149.125\",\n    \"l\": \"149.1145\",\n    \"o\": \"149.116\",\n    \"t\": \"Nov 21, 2017 4:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1325\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.11\",\n    \"o\": \"149.1185\",\n    \"t\": \"Nov 21, 2017 4:03:00 AM\"\n  },\n  {\n    \"c\": \"149.152\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1325\",\n    \"o\": \"149.1325\",\n    \"t\": \"Nov 21, 2017 4:04:00 AM\"\n  },\n  {\n    \"c\": \"149.161\",\n    \"h\": \"149.164\",\n    \"l\": \"149.152\",\n    \"o\": \"149.152\",\n    \"t\": \"Nov 21, 2017 4:05:00 AM\"\n  },\n  {\n    \"c\": \"149.1595\",\n    \"h\": \"149.169\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1615\",\n    \"t\": \"Nov 21, 2017 4:06:00 AM\"\n  },\n  {\n    \"c\": \"149.1475\",\n    \"h\": \"149.166\",\n    \"l\": \"149.144\",\n    \"o\": \"149.1595\",\n    \"t\": \"Nov 21, 2017 4:07:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.152\",\n    \"l\": \"149.137\",\n    \"o\": \"149.148\",\n    \"t\": \"Nov 21, 2017 4:08:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.1485\",\n    \"l\": \"149.1345\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 4:09:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.144\",\n    \"l\": \"149.1265\",\n    \"o\": \"149.137\",\n    \"t\": \"Nov 21, 2017 4:10:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.152\",\n    \"l\": \"149.1365\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 4:11:00 AM\"\n  },\n  {\n    \"c\": \"149.1355\",\n    \"h\": \"149.1475\",\n    \"l\": \"149.133\",\n    \"o\": \"149.1475\",\n    \"t\": \"Nov 21, 2017 4:12:00 AM\"\n  },\n  {\n    \"c\": \"149.116\",\n    \"h\": \"149.138\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1355\",\n    \"t\": \"Nov 21, 2017 4:13:00 AM\"\n  },\n  {\n    \"c\": \"149.13\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1165\",\n    \"t\": \"Nov 21, 2017 4:14:00 AM\"\n  },\n  {\n    \"c\": \"149.124\",\n    \"h\": \"149.13\",\n    \"l\": \"149.1195\",\n    \"o\": \"149.1295\",\n    \"t\": \"Nov 21, 2017 4:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1265\",\n    \"h\": \"149.1285\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.1245\",\n    \"t\": \"Nov 21, 2017 4:16:00 AM\"\n  },\n  {\n    \"c\": \"149.123\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.112\",\n    \"o\": \"149.128\",\n    \"t\": \"Nov 21, 2017 4:17:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.126\",\n    \"l\": \"149.109\",\n    \"o\": \"149.1225\",\n    \"t\": \"Nov 21, 2017 4:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1125\",\n    \"h\": \"149.123\",\n    \"l\": \"149.11\",\n    \"o\": \"149.1145\",\n    \"t\": \"Nov 21, 2017 4:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.117\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.112\",\n    \"t\": \"Nov 21, 2017 4:20:00 AM\"\n  },\n  {\n    \"c\": \"149.106\",\n    \"h\": \"149.115\",\n    \"l\": \"149.1045\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 4:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.105\",\n    \"l\": \"149.094\",\n    \"o\": \"149.1045\",\n    \"t\": \"Nov 21, 2017 4:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1195\",\n    \"h\": \"149.1195\",\n    \"l\": \"149.095\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 4:23:00 AM\"\n  },\n  {\n    \"c\": \"149.123\",\n    \"h\": \"149.1305\",\n    \"l\": \"149.115\",\n    \"o\": \"149.119\",\n    \"t\": \"Nov 21, 2017 4:24:00 AM\"\n  },\n  {\n    \"c\": \"149.134\",\n    \"h\": \"149.1355\",\n    \"l\": \"149.1215\",\n    \"o\": \"149.122\",\n    \"t\": \"Nov 21, 2017 4:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1215\",\n    \"h\": \"149.137\",\n    \"l\": \"149.12\",\n    \"o\": \"149.134\",\n    \"t\": \"Nov 21, 2017 4:26:00 AM\"\n  },\n  {\n    \"c\": \"149.1335\",\n    \"h\": \"149.137\",\n    \"l\": \"149.118\",\n    \"o\": \"149.1205\",\n    \"t\": \"Nov 21, 2017 4:27:00 AM\"\n  },\n  {\n    \"c\": \"149.144\",\n    \"h\": \"149.1525\",\n    \"l\": \"149.134\",\n    \"o\": \"149.134\",\n    \"t\": \"Nov 21, 2017 4:28:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.1585\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.1445\",\n    \"t\": \"Nov 21, 2017 4:29:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.151\",\n    \"l\": \"149.136\",\n    \"o\": \"149.1435\",\n    \"t\": \"Nov 21, 2017 4:30:00 AM\"\n  },\n  {\n    \"c\": \"149.114\",\n    \"h\": \"149.147\",\n    \"l\": \"149.114\",\n    \"o\": \"149.146\",\n    \"t\": \"Nov 21, 2017 4:31:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.1025\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 4:32:00 AM\"\n  },\n  {\n    \"c\": \"149.0985\",\n    \"h\": \"149.1115\",\n    \"l\": \"149.096\",\n    \"o\": \"149.1035\",\n    \"t\": \"Nov 21, 2017 4:33:00 AM\"\n  },\n  {\n    \"c\": \"149.0995\",\n    \"h\": \"149.1005\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 4:34:00 AM\"\n  },\n  {\n    \"c\": \"149.088\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 4:35:00 AM\"\n  },\n  {\n    \"c\": \"149.089\",\n    \"h\": \"149.089\",\n    \"l\": \"149.082\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 4:36:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.095\",\n    \"l\": \"149.0815\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 4:37:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 4:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0945\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.09\",\n    \"t\": \"Nov 21, 2017 4:39:00 AM\"\n  },\n  {\n    \"c\": \"149.098\",\n    \"h\": \"149.099\",\n    \"l\": \"149.0835\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 4:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0815\",\n    \"h\": \"149.0995\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.098\",\n    \"t\": \"Nov 21, 2017 4:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0875\",\n    \"h\": \"149.092\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 4:42:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 4:43:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.079\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 4:44:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.0795\",\n    \"t\": \"Nov 21, 2017 4:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.0715\",\n    \"o\": \"149.075\",\n    \"t\": \"Nov 21, 2017 4:46:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.079\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 4:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0835\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.077\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 4:48:00 AM\"\n  },\n  {\n    \"c\": \"149.0765\",\n    \"h\": \"149.083\",\n    \"l\": \"149.073\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 4:49:00 AM\"\n  },\n  {\n    \"c\": \"149.069\",\n    \"h\": \"149.078\",\n    \"l\": \"149.0665\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 4:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.076\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.07\",\n    \"t\": \"Nov 21, 2017 4:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0735\",\n    \"h\": \"149.076\",\n    \"l\": \"149.064\",\n    \"o\": \"149.0725\",\n    \"t\": \"Nov 21, 2017 4:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0675\",\n    \"h\": \"149.0735\",\n    \"l\": \"149.063\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 4:53:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.083\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.067\",\n    \"t\": \"Nov 21, 2017 4:54:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0645\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 4:55:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.0795\",\n    \"l\": \"149.061\",\n    \"o\": \"149.0785\",\n    \"t\": \"Nov 21, 2017 4:56:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.0655\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 4:57:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 4:58:00 AM\"\n  },\n  {\n    \"c\": \"149.031\",\n    \"h\": \"149.0545\",\n    \"l\": \"149.025\",\n    \"o\": \"149.043\",\n    \"t\": \"Nov 21, 2017 4:59:00 AM\"\n  },\n  {\n    \"c\": \"149.0095\",\n    \"h\": \"149.0455\",\n    \"l\": \"149.002\",\n    \"o\": \"149.0305\",\n    \"t\": \"Nov 21, 2017 5:00:00 AM\"\n  },\n  {\n    \"c\": \"149.007\",\n    \"h\": \"149.015\",\n    \"l\": \"149.0\",\n    \"o\": \"149.01\",\n    \"t\": \"Nov 21, 2017 5:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0045\",\n    \"h\": \"149.0095\",\n    \"l\": \"149.0\",\n    \"o\": \"149.008\",\n    \"t\": \"Nov 21, 2017 5:02:00 AM\"\n  },\n  {\n    \"c\": \"148.997\",\n    \"h\": \"149.0035\",\n    \"l\": \"148.9915\",\n    \"o\": \"149.0035\",\n    \"t\": \"Nov 21, 2017 5:03:00 AM\"\n  },\n  {\n    \"c\": \"148.989\",\n    \"h\": \"148.998\",\n    \"l\": \"148.985\",\n    \"o\": \"148.997\",\n    \"t\": \"Nov 21, 2017 5:04:00 AM\"\n  },\n  {\n    \"c\": \"148.9855\",\n    \"h\": \"149.0\",\n    \"l\": \"148.9825\",\n    \"o\": \"148.99\",\n    \"t\": \"Nov 21, 2017 5:05:00 AM\"\n  },\n  {\n    \"c\": \"148.977\",\n    \"h\": \"148.9935\",\n    \"l\": \"148.974\",\n    \"o\": \"148.986\",\n    \"t\": \"Nov 21, 2017 5:06:00 AM\"\n  },\n  {\n    \"c\": \"148.97\",\n    \"h\": \"148.9815\",\n    \"l\": \"148.961\",\n    \"o\": \"148.9765\",\n    \"t\": \"Nov 21, 2017 5:07:00 AM\"\n  },\n  {\n    \"c\": \"148.9865\",\n    \"h\": \"148.988\",\n    \"l\": \"148.9675\",\n    \"o\": \"148.9695\",\n    \"t\": \"Nov 21, 2017 5:08:00 AM\"\n  },\n  {\n    \"c\": \"149.002\",\n    \"h\": \"149.002\",\n    \"l\": \"148.9855\",\n    \"o\": \"148.9865\",\n    \"t\": \"Nov 21, 2017 5:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0085\",\n    \"h\": \"149.014\",\n    \"l\": \"148.9905\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:10:00 AM\"\n  },\n  {\n    \"c\": \"149.007\",\n    \"h\": \"149.0085\",\n    \"l\": \"148.9965\",\n    \"o\": \"149.0075\",\n    \"t\": \"Nov 21, 2017 5:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0185\",\n    \"h\": \"149.0185\",\n    \"l\": \"149.007\",\n    \"o\": \"149.007\",\n    \"t\": \"Nov 21, 2017 5:12:00 AM\"\n  },\n  {\n    \"c\": \"149.0165\",\n    \"h\": \"149.0215\",\n    \"l\": \"149.0135\",\n    \"o\": \"149.0185\",\n    \"t\": \"Nov 21, 2017 5:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0305\",\n    \"h\": \"149.033\",\n    \"l\": \"149.0145\",\n    \"o\": \"149.0175\",\n    \"t\": \"Nov 21, 2017 5:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0365\",\n    \"h\": \"149.0375\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.03\",\n    \"t\": \"Nov 21, 2017 5:15:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.04\",\n    \"l\": \"149.033\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 5:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.047\",\n    \"l\": \"149.0375\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 5:17:00 AM\"\n  },\n  {\n    \"c\": \"149.0455\",\n    \"h\": \"149.051\",\n    \"l\": \"149.038\",\n    \"o\": \"149.0405\",\n    \"t\": \"Nov 21, 2017 5:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0535\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0455\",\n    \"o\": \"149.0455\",\n    \"t\": \"Nov 21, 2017 5:19:00 AM\"\n  },\n  {\n    \"c\": \"149.055\",\n    \"h\": \"149.059\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 5:20:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.0455\",\n    \"o\": \"149.055\",\n    \"t\": \"Nov 21, 2017 5:21:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0495\",\n    \"o\": \"149.0635\",\n    \"t\": \"Nov 21, 2017 5:22:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.051\",\n    \"t\": \"Nov 21, 2017 5:23:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0645\",\n    \"l\": \"149.046\",\n    \"o\": \"149.0645\",\n    \"t\": \"Nov 21, 2017 5:24:00 AM\"\n  },\n  {\n    \"c\": \"149.0645\",\n    \"h\": \"149.0645\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.056\",\n    \"t\": \"Nov 21, 2017 5:25:00 AM\"\n  },\n  {\n    \"c\": \"149.076\",\n    \"h\": \"149.077\",\n    \"l\": \"149.063\",\n    \"o\": \"149.063\",\n    \"t\": \"Nov 21, 2017 5:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0805\",\n    \"l\": \"149.0725\",\n    \"o\": \"149.0755\",\n    \"t\": \"Nov 21, 2017 5:27:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.087\",\n    \"l\": \"149.08\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 5:28:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.084\",\n    \"t\": \"Nov 21, 2017 5:29:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 5:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0975\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 5:31:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.1015\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 5:32:00 AM\"\n  },\n  {\n    \"c\": \"149.107\",\n    \"h\": \"149.1095\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.0835\",\n    \"t\": \"Nov 21, 2017 5:33:00 AM\"\n  },\n  {\n    \"c\": \"149.1025\",\n    \"h\": \"149.113\",\n    \"l\": \"149.095\",\n    \"o\": \"149.1055\",\n    \"t\": \"Nov 21, 2017 5:34:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.1035\",\n    \"l\": \"149.0935\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 5:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.097\",\n    \"l\": \"149.091\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 5:36:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0835\",\n    \"o\": \"149.0925\",\n    \"t\": \"Nov 21, 2017 5:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0755\",\n    \"h\": \"149.087\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 5:38:00 AM\"\n  },\n  {\n    \"c\": \"149.05\",\n    \"h\": \"149.078\",\n    \"l\": \"149.0495\",\n    \"o\": \"149.0765\",\n    \"t\": \"Nov 21, 2017 5:39:00 AM\"\n  },\n  {\n    \"c\": \"149.018\",\n    \"h\": \"149.051\",\n    \"l\": \"149.0155\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 5:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0365\",\n    \"h\": \"149.037\",\n    \"l\": \"149.0175\",\n    \"o\": \"149.018\",\n    \"t\": \"Nov 21, 2017 5:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.0375\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 5:42:00 AM\"\n  },\n  {\n    \"c\": \"149.057\",\n    \"h\": \"149.07\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 5:43:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0575\",\n    \"t\": \"Nov 21, 2017 5:44:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.074\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.0655\",\n    \"t\": \"Nov 21, 2017 5:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.084\",\n    \"l\": \"149.0725\",\n    \"o\": \"149.0735\",\n    \"t\": \"Nov 21, 2017 5:46:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.08\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 5:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0685\",\n    \"h\": \"149.0775\",\n    \"l\": \"149.068\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 5:48:00 AM\"\n  },\n  {\n    \"c\": \"149.067\",\n    \"h\": \"149.0685\",\n    \"l\": \"149.066\",\n    \"o\": \"149.067\",\n    \"t\": \"Nov 21, 2017 5:49:00 AM\"\n  },\n  {\n    \"c\": \"149.045\",\n    \"h\": \"149.073\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.066\",\n    \"t\": \"Nov 21, 2017 5:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.046\",\n    \"l\": \"149.0225\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 5:51:00 AM\"\n  },\n  {\n    \"c\": \"149.004\",\n    \"h\": \"149.023\",\n    \"l\": \"149.004\",\n    \"o\": \"149.023\",\n    \"t\": \"Nov 21, 2017 5:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0175\",\n    \"h\": \"149.022\",\n    \"l\": \"149.0045\",\n    \"o\": \"149.0045\",\n    \"t\": \"Nov 21, 2017 5:53:00 AM\"\n  },\n  {\n    \"c\": \"149.011\",\n    \"h\": \"149.0195\",\n    \"l\": \"149.008\",\n    \"o\": \"149.0175\",\n    \"t\": \"Nov 21, 2017 5:54:00 AM\"\n  },\n  {\n    \"c\": \"149.009\",\n    \"h\": \"149.0115\",\n    \"l\": \"149.001\",\n    \"o\": \"149.0115\",\n    \"t\": \"Nov 21, 2017 5:55:00 AM\"\n  },\n  {\n    \"c\": \"149.001\",\n    \"h\": \"149.0155\",\n    \"l\": \"148.9975\",\n    \"o\": \"149.007\",\n    \"t\": \"Nov 21, 2017 5:56:00 AM\"\n  },\n  {\n    \"c\": \"149.0025\",\n    \"h\": \"149.005\",\n    \"l\": \"148.998\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:57:00 AM\"\n  },\n  {\n    \"c\": \"149.041\",\n    \"h\": \"149.0555\",\n    \"l\": \"149.0025\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:58:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.069\",\n    \"l\": \"149.033\",\n    \"o\": \"149.042\",\n    \"t\": \"Nov 21, 2017 5:59:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.0805\",\n    \"l\": \"149.0405\",\n    \"o\": \"149.0805\",\n    \"t\": \"Nov 21, 2017 6:00:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.039\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 6:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0415\",\n    \"h\": \"149.0415\",\n    \"l\": \"149.0355\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:02:00 AM\"\n  },\n  {\n    \"c\": \"149.0635\",\n    \"h\": \"149.0635\",\n    \"l\": \"149.0415\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 6:03:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.1045\",\n    \"l\": \"149.064\",\n    \"o\": \"149.064\",\n    \"t\": \"Nov 21, 2017 6:04:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.105\",\n    \"l\": \"149.0915\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 6:05:00 AM\"\n  },\n  {\n    \"c\": \"149.0815\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0925\",\n    \"t\": \"Nov 21, 2017 6:06:00 AM\"\n  },\n  {\n    \"c\": \"149.0875\",\n    \"h\": \"149.0885\",\n    \"l\": \"149.082\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 6:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0925\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:08:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.0945\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0935\",\n    \"t\": \"Nov 21, 2017 6:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.088\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:11:00 AM\"\n  },\n  {\n    \"c\": \"149.097\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0945\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 6:12:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0965\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.097\",\n    \"l\": \"149.0965\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:14:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.092\",\n    \"o\": \"149.095\",\n    \"t\": \"Nov 21, 2017 6:15:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.099\",\n    \"l\": \"149.094\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 6:17:00 AM\"\n  },\n  {\n    \"c\": \"149.1015\",\n    \"h\": \"149.102\",\n    \"l\": \"149.0885\",\n    \"o\": \"149.091\",\n    \"t\": \"Nov 21, 2017 6:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0955\",\n    \"h\": \"149.107\",\n    \"l\": \"149.0905\",\n    \"o\": \"149.1005\",\n    \"t\": \"Nov 21, 2017 6:19:00 AM\"\n  },\n  {\n    \"c\": \"149.0935\",\n    \"h\": \"149.105\",\n    \"l\": \"149.0905\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 6:20:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.094\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 6:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0925\",\n    \"h\": \"149.096\",\n    \"l\": \"149.0925\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 6:22:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0855\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:23:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.09\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:24:00 AM\"\n  },\n  {\n    \"c\": \"149.088\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:25:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.0875\",\n    \"l\": \"149.084\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 6:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.0635\",\n    \"o\": \"149.0825\",\n    \"t\": \"Nov 21, 2017 6:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.0865\",\n    \"l\": \"149.078\",\n    \"o\": \"149.0795\",\n    \"t\": \"Nov 21, 2017 6:28:00 AM\"\n  },\n  {\n    \"c\": \"149.065\",\n    \"h\": \"149.0885\",\n    \"l\": \"149.062\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 6:29:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.065\",\n    \"l\": \"149.052\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 6:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.094\",\n    \"l\": \"149.061\",\n    \"o\": \"149.0625\",\n    \"t\": \"Nov 21, 2017 6:31:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:32:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.088\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 6:33:00 AM\"\n  },\n  {\n    \"c\": \"149.089\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:34:00 AM\"\n  },\n  {\n    \"c\": \"149.0865\",\n    \"h\": \"149.095\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:35:00 AM\"\n  },\n  {\n    \"c\": \"149.097\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 6:36:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 6:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.095\",\n    \"l\": \"149.067\",\n    \"o\": \"149.092\",\n    \"t\": \"Nov 21, 2017 6:38:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.0815\",\n    \"l\": \"149.074\",\n    \"o\": \"149.074\",\n    \"t\": \"Nov 21, 2017 6:39:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 6:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0785\",\n    \"h\": \"149.08\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.077\",\n    \"t\": \"Nov 21, 2017 6:41:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 6:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0765\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.076\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 6:43:00 AM\"\n  },\n  {\n    \"c\": \"149.075\",\n    \"h\": \"149.0765\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 6:44:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0745\",\n    \"l\": \"149.053\",\n    \"o\": \"149.0745\",\n    \"t\": \"Nov 21, 2017 6:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0375\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0355\",\n    \"o\": \"149.0555\",\n    \"t\": \"Nov 21, 2017 6:46:00 AM\"\n  },\n  {\n    \"c\": \"149.0415\",\n    \"h\": \"149.0425\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.0395\",\n    \"t\": \"Nov 21, 2017 6:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0445\",\n    \"h\": \"149.045\",\n    \"l\": \"149.04\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:48:00 AM\"\n  },\n  {\n    \"c\": \"149.059\",\n    \"h\": \"149.06\",\n    \"l\": \"149.045\",\n    \"o\": \"149.0455\",\n    \"t\": \"Nov 21, 2017 6:49:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.059\",\n    \"l\": \"149.049\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 6:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.054\",\n    \"l\": \"149.05\",\n    \"o\": \"149.0515\",\n    \"t\": \"Nov 21, 2017 6:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.052\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.052\",\n    \"t\": \"Nov 21, 2017 6:52:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.0475\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:53:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.04\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 6:54:00 AM\"\n  },\n  {\n    \"c\": \"149.0345\",\n    \"h\": \"149.04\",\n    \"l\": \"149.034\",\n    \"o\": \"149.0385\",\n    \"t\": \"Nov 21, 2017 6:55:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.045\",\n    \"l\": \"149.034\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 6:56:00 AM\"\n  },\n  {\n    \"c\": \"149.0245\",\n    \"h\": \"149.0425\",\n    \"l\": \"149.022\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 6:57:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.037\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 6:58:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.0285\",\n    \"l\": \"149.015\",\n    \"o\": \"149.0285\",\n    \"t\": \"Nov 21, 2017 6:59:00 AM\"\n  },\n  {\n    \"c\": \"149.032\",\n    \"h\": \"149.033\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 7:00:00 AM\"\n  },\n  {\n    \"c\": \"149.025\",\n    \"h\": \"149.035\",\n    \"l\": \"149.022\",\n    \"o\": \"149.031\",\n    \"t\": \"Nov 21, 2017 7:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0245\",\n    \"h\": \"149.029\",\n    \"l\": \"149.011\",\n    \"o\": \"149.0245\",\n    \"t\": \"Nov 21, 2017 7:02:00 AM\"\n  },\n  {\n    \"c\": \"149.019\",\n    \"h\": \"149.029\",\n    \"l\": \"149.0135\",\n    \"o\": \"149.026\",\n    \"t\": \"Nov 21, 2017 7:03:00 AM\"\n  },\n  {\n    \"c\": \"149.011\",\n    \"h\": \"149.02\",\n    \"l\": \"149.011\",\n    \"o\": \"149.02\",\n    \"t\": \"Nov 21, 2017 7:04:00 AM\"\n  },\n  {\n    \"c\": \"149.0035\",\n    \"h\": \"149.0165\",\n    \"l\": \"148.9985\",\n    \"o\": \"149.012\",\n    \"t\": \"Nov 21, 2017 7:05:00 AM\"\n  },\n  {\n    \"c\": \"149.012\",\n    \"h\": \"149.012\",\n    \"l\": \"148.9965\",\n    \"o\": \"149.0045\",\n    \"t\": \"Nov 21, 2017 7:06:00 AM\"\n  },\n  {\n    \"c\": \"148.989\",\n    \"h\": \"149.014\",\n    \"l\": \"148.987\",\n    \"o\": \"149.0115\",\n    \"t\": \"Nov 21, 2017 7:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0215\",\n    \"h\": \"149.0225\",\n    \"l\": \"148.991\",\n    \"o\": \"148.991\",\n    \"t\": \"Nov 21, 2017 7:08:00 AM\"\n  },\n  {\n    \"c\": \"149.0195\",\n    \"h\": \"149.024\",\n    \"l\": \"149.019\",\n    \"o\": \"149.019\",\n    \"t\": \"Nov 21, 2017 7:09:00 AM\"\n  },\n  {\n    \"c\": \"149.024\",\n    \"h\": \"149.0255\",\n    \"l\": \"149.017\",\n    \"o\": \"149.018\",\n    \"t\": \"Nov 21, 2017 7:10:00 AM\"\n  },\n  {\n    \"c\": \"149.052\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.02\",\n    \"o\": \"149.0225\",\n    \"t\": \"Nov 21, 2017 7:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0485\",\n    \"h\": \"149.0545\",\n    \"l\": \"149.048\",\n    \"o\": \"149.052\",\n    \"t\": \"Nov 21, 2017 7:12:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.048\",\n    \"l\": \"149.041\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:13:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.043\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.043\",\n    \"t\": \"Nov 21, 2017 7:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0335\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.0305\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 7:15:00 AM\"\n  },\n  {\n    \"c\": \"149.0285\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.027\",\n    \"o\": \"149.0325\",\n    \"t\": \"Nov 21, 2017 7:16:00 AM\"\n  },\n  {\n    \"c\": \"149.027\",\n    \"h\": \"149.03\",\n    \"l\": \"149.0225\",\n    \"o\": \"149.0285\",\n    \"t\": \"Nov 21, 2017 7:17:00 AM\"\n  },\n  {\n    \"c\": \"149.0295\",\n    \"h\": \"149.03\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0265\",\n    \"t\": \"Nov 21, 2017 7:18:00 AM\"\n  },\n  {\n    \"c\": \"149.031\",\n    \"h\": \"149.031\",\n    \"l\": \"149.027\",\n    \"o\": \"149.0295\",\n    \"t\": \"Nov 21, 2017 7:19:00 AM\"\n  },\n  {\n    \"c\": \"149.028\",\n    \"h\": \"149.031\",\n    \"l\": \"149.028\",\n    \"o\": \"149.029\",\n    \"t\": \"Nov 21, 2017 7:20:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.0375\",\n    \"l\": \"149.0265\",\n    \"o\": \"149.027\",\n    \"t\": \"Nov 21, 2017 7:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.043\",\n    \"l\": \"149.0325\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 7:22:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.037\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.037\",\n    \"t\": \"Nov 21, 2017 7:23:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.033\",\n    \"o\": \"149.033\",\n    \"t\": \"Nov 21, 2017 7:24:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.03\",\n    \"o\": \"149.033\",\n    \"t\": \"Nov 21, 2017 7:25:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0345\",\n    \"l\": \"149.033\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 7:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0435\",\n    \"l\": \"149.032\",\n    \"o\": \"149.0325\",\n    \"t\": \"Nov 21, 2017 7:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0465\",\n    \"h\": \"149.05\",\n    \"l\": \"149.0425\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:28:00 AM\"\n  },\n  {\n    \"c\": \"149.0475\",\n    \"h\": \"149.0485\",\n    \"l\": \"149.0465\",\n    \"o\": \"149.047\",\n    \"t\": \"Nov 21, 2017 7:29:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0595\",\n    \"l\": \"149.048\",\n    \"o\": \"149.048\",\n    \"t\": \"Nov 21, 2017 7:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0595\",\n    \"h\": \"149.06\",\n    \"l\": \"149.057\",\n    \"o\": \"149.057\",\n    \"t\": \"Nov 21, 2017 7:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0605\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.056\",\n    \"o\": \"149.058\",\n    \"t\": \"Nov 21, 2017 7:32:00 AM\"\n  },\n  {\n    \"c\": \"149.067\",\n    \"h\": \"149.07\",\n    \"l\": \"149.059\",\n    \"o\": \"149.062\",\n    \"t\": \"Nov 21, 2017 7:33:00 AM\"\n  },\n  {\n    \"c\": \"149.063\",\n    \"h\": \"149.075\",\n    \"l\": \"149.063\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 7:34:00 AM\"\n  },\n  {\n    \"c\": \"149.062\",\n    \"h\": \"149.065\",\n    \"l\": \"149.0615\",\n    \"o\": \"149.0635\",\n    \"t\": \"Nov 21, 2017 7:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.063\",\n    \"l\": \"149.061\",\n    \"o\": \"149.061\",\n    \"t\": \"Nov 21, 2017 7:36:00 AM\"\n  },\n  {\n    \"c\": \"149.06\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.056\",\n    \"o\": \"149.062\",\n    \"t\": \"Nov 21, 2017 7:37:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.085\",\n    \"l\": \"149.059\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 7:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.085\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 7:39:00 AM\"\n  },\n  {\n    \"c\": \"149.0705\",\n    \"h\": \"149.0735\",\n    \"l\": \"149.0685\",\n    \"o\": \"149.073\",\n    \"t\": \"Nov 21, 2017 7:40:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.074\",\n    \"l\": \"149.0635\",\n    \"o\": \"149.07\",\n    \"t\": \"Nov 21, 2017 7:41:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.077\",\n    \"l\": \"149.058\",\n    \"o\": \"149.0665\",\n    \"t\": \"Nov 21, 2017 7:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0705\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.066\",\n    \"o\": \"149.077\",\n    \"t\": \"Nov 21, 2017 7:43:00 AM\"\n  },\n  {\n    \"c\": \"149.059\",\n    \"h\": \"149.0775\",\n    \"l\": \"149.058\",\n    \"o\": \"149.071\",\n    \"t\": \"Nov 21, 2017 7:44:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.08\",\n    \"l\": \"149.052\",\n    \"o\": \"149.0595\",\n    \"t\": \"Nov 21, 2017 7:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0605\",\n    \"h\": \"149.077\",\n    \"l\": \"149.0605\",\n    \"o\": \"149.0765\",\n    \"t\": \"Nov 21, 2017 7:46:00 AM\"\n  },\n  {\n    \"c\": \"149.044\",\n    \"h\": \"149.0605\",\n    \"l\": \"149.038\",\n    \"o\": \"149.06\",\n    \"t\": \"Nov 21, 2017 7:47:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.063\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:48:00 AM\"\n  },\n  {\n    \"c\": \"149.06\",\n    \"h\": \"149.06\",\n    \"l\": \"149.048\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 7:49:00 AM\"\n  },\n  {\n    \"c\": \"149.058\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.0565\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 7:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0555\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.0555\",\n    \"o\": \"149.058\",\n    \"t\": \"Nov 21, 2017 7:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0125\",\n    \"h\": \"149.056\",\n    \"l\": \"149.0125\",\n    \"o\": \"149.054\",\n    \"t\": \"Nov 21, 2017 7:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0165\",\n    \"h\": \"149.02\",\n    \"l\": \"149.0015\",\n    \"o\": \"149.0135\",\n    \"t\": \"Nov 21, 2017 7:53:00 AM\"\n  },\n  {\n    \"c\": \"149.026\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.007\",\n    \"o\": \"149.0145\",\n    \"t\": \"Nov 21, 2017 7:54:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.0355\",\n    \"l\": \"149.0235\",\n    \"o\": \"149.0255\",\n    \"t\": \"Nov 21, 2017 7:55:00 AM\"\n  },\n  {\n    \"c\": \"149.036\",\n    \"h\": \"149.0495\",\n    \"l\": \"149.0305\",\n    \"o\": \"149.0305\",\n    \"t\": \"Nov 21, 2017 7:56:00 AM\"\n  },\n  {\n    \"c\": \"149.041\",\n    \"h\": \"149.042\",\n    \"l\": \"149.036\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 7:57:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.0405\",\n    \"o\": \"149.042\",\n    \"t\": \"Nov 21, 2017 7:58:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.052\",\n    \"l\": \"149.043\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 7:59:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.0565\",\n    \"l\": \"149.032\",\n    \"o\": \"149.047\",\n    \"t\": \"Nov 21, 2017 8:00:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.096\",\n    \"l\": \"149.036\",\n    \"o\": \"149.0425\",\n    \"t\": \"Nov 21, 2017 8:01:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.104\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 8:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1095\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.083\",\n    \"o\": \"149.104\",\n    \"t\": \"Nov 21, 2017 8:03:00 AM\"\n  },\n  {\n    \"c\": \"149.126\",\n    \"h\": \"149.1395\",\n    \"l\": \"149.109\",\n    \"o\": \"149.11\",\n    \"t\": \"Nov 21, 2017 8:04:00 AM\"\n  },\n  {\n    \"c\": \"149.127\",\n    \"h\": \"149.141\",\n    \"l\": \"149.123\",\n    \"o\": \"149.1255\",\n    \"t\": \"Nov 21, 2017 8:05:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.138\",\n    \"l\": \"149.112\",\n    \"o\": \"149.126\",\n    \"t\": \"Nov 21, 2017 8:06:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.1185\",\n    \"l\": \"149.078\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 8:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0825\",\n    \"h\": \"149.0875\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 8:08:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.0665\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 8:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0545\",\n    \"h\": \"149.076\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.0745\",\n    \"t\": \"Nov 21, 2017 8:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0685\",\n    \"h\": \"149.0695\",\n    \"l\": \"149.0525\",\n    \"o\": \"149.053\",\n    \"t\": \"Nov 21, 2017 8:11:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.1025\",\n    \"l\": \"149.063\",\n    \"o\": \"149.068\",\n    \"t\": \"Nov 21, 2017 8:12:00 AM\"\n  },\n  {\n    \"c\": \"149.116\",\n    \"h\": \"149.1195\",\n    \"l\": \"149.0935\",\n    \"o\": \"149.0935\",\n    \"t\": \"Nov 21, 2017 8:13:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.103\",\n    \"o\": \"149.1155\",\n    \"t\": \"Nov 21, 2017 8:14:00 AM\"\n  },\n  {\n    \"c\": \"149.1065\",\n    \"h\": \"149.124\",\n    \"l\": \"149.099\",\n    \"o\": \"149.1025\",\n    \"t\": \"Nov 21, 2017 8:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1125\",\n    \"h\": \"149.1135\",\n    \"l\": \"149.1005\",\n    \"o\": \"149.1075\",\n    \"t\": \"Nov 21, 2017 8:16:00 AM\"\n  },\n  {\n    \"c\": \"149.1295\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1125\",\n    \"o\": \"149.1125\",\n    \"t\": \"Nov 21, 2017 8:17:00 AM\"\n  },\n  {\n    \"c\": \"149.135\",\n    \"h\": \"149.1375\",\n    \"l\": \"149.1225\",\n    \"o\": \"149.1285\",\n    \"t\": \"Nov 21, 2017 8:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.1395\",\n    \"l\": \"149.1325\",\n    \"o\": \"149.135\",\n    \"t\": \"Nov 21, 2017 8:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1615\",\n    \"h\": \"149.17\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1375\",\n    \"t\": \"Nov 21, 2017 8:20:00 AM\"\n  },\n  {\n    \"c\": \"149.1415\",\n    \"h\": \"149.173\",\n    \"l\": \"149.141\",\n    \"o\": \"149.162\",\n    \"t\": \"Nov 21, 2017 8:21:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.153\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1425\",\n    \"t\": \"Nov 21, 2017 8:22:00 AM\"\n  },\n  {\n    \"c\": \"149.131\",\n    \"h\": \"149.1465\",\n    \"l\": \"149.126\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 8:23:00 AM\"\n  },\n  {\n    \"c\": \"149.1325\",\n    \"h\": \"149.1365\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 8:24:00 AM\"\n  },\n  {\n    \"c\": \"149.1565\",\n    \"h\": \"149.157\",\n    \"l\": \"149.1335\",\n    \"o\": \"149.1335\",\n    \"t\": \"Nov 21, 2017 8:25:00 AM\"\n  },\n  {\n    \"c\": \"149.208\",\n    \"h\": \"149.21\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1555\",\n    \"t\": \"Nov 21, 2017 8:26:00 AM\"\n  },\n  {\n    \"c\": \"149.198\",\n    \"h\": \"149.218\",\n    \"l\": \"149.1915\",\n    \"o\": \"149.207\",\n    \"t\": \"Nov 21, 2017 8:27:00 AM\"\n  },\n  {\n    \"c\": \"149.202\",\n    \"h\": \"149.207\",\n    \"l\": \"149.195\",\n    \"o\": \"149.196\",\n    \"t\": \"Nov 21, 2017 8:28:00 AM\"\n  },\n  {\n    \"c\": \"149.216\",\n    \"h\": \"149.2235\",\n    \"l\": \"149.191\",\n    \"o\": \"149.2035\",\n    \"t\": \"Nov 21, 2017 8:29:00 AM\"\n  },\n  {\n    \"c\": \"149.193\",\n    \"h\": \"149.216\",\n    \"l\": \"149.185\",\n    \"o\": \"149.2145\",\n    \"t\": \"Nov 21, 2017 8:30:00 AM\"\n  },\n  {\n    \"c\": \"149.1835\",\n    \"h\": \"149.197\",\n    \"l\": \"149.1835\",\n    \"o\": \"149.193\",\n    \"t\": \"Nov 21, 2017 8:31:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1905\",\n    \"l\": \"149.1735\",\n    \"o\": \"149.182\",\n    \"t\": \"Nov 21, 2017 8:32:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1835\",\n    \"l\": \"149.1705\",\n    \"o\": \"149.174\",\n    \"t\": \"Nov 21, 2017 8:33:00 AM\"\n  },\n  {\n    \"c\": \"149.1795\",\n    \"h\": \"149.187\",\n    \"l\": \"149.1715\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:34:00 AM\"\n  },\n  {\n    \"c\": \"149.2055\",\n    \"h\": \"149.209\",\n    \"l\": \"149.1805\",\n    \"o\": \"149.1805\",\n    \"t\": \"Nov 21, 2017 8:35:00 AM\"\n  },\n  {\n    \"c\": \"149.194\",\n    \"h\": \"149.2095\",\n    \"l\": \"149.1925\",\n    \"o\": \"149.2055\",\n    \"t\": \"Nov 21, 2017 8:36:00 AM\"\n  },\n  {\n    \"c\": \"149.1955\",\n    \"h\": \"149.2\",\n    \"l\": \"149.1845\",\n    \"o\": \"149.1935\",\n    \"t\": \"Nov 21, 2017 8:37:00 AM\"\n  },\n  {\n    \"c\": \"149.1995\",\n    \"h\": \"149.211\",\n    \"l\": \"149.184\",\n    \"o\": \"149.194\",\n    \"t\": \"Nov 21, 2017 8:38:00 AM\"\n  },\n  {\n    \"c\": \"149.202\",\n    \"h\": \"149.206\",\n    \"l\": \"149.1905\",\n    \"o\": \"149.199\",\n    \"t\": \"Nov 21, 2017 8:39:00 AM\"\n  },\n  {\n    \"c\": \"149.184\",\n    \"h\": \"149.2025\",\n    \"l\": \"149.17\",\n    \"o\": \"149.202\",\n    \"t\": \"Nov 21, 2017 8:40:00 AM\"\n  },\n  {\n    \"c\": \"149.187\",\n    \"h\": \"149.1945\",\n    \"l\": \"149.174\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 8:41:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1865\",\n    \"t\": \"Nov 21, 2017 8:42:00 AM\"\n  },\n  {\n    \"c\": \"149.146\",\n    \"h\": \"149.177\",\n    \"l\": \"149.146\",\n    \"o\": \"149.176\",\n    \"t\": \"Nov 21, 2017 8:43:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.1615\",\n    \"l\": \"149.1395\",\n    \"o\": \"149.1455\",\n    \"t\": \"Nov 21, 2017 8:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1605\",\n    \"h\": \"149.162\",\n    \"l\": \"149.1405\",\n    \"o\": \"149.1445\",\n    \"t\": \"Nov 21, 2017 8:45:00 AM\"\n  },\n  {\n    \"c\": \"149.1515\",\n    \"h\": \"149.1605\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.1605\",\n    \"t\": \"Nov 21, 2017 8:46:00 AM\"\n  },\n  {\n    \"c\": \"149.1515\",\n    \"h\": \"149.152\",\n    \"l\": \"149.144\",\n    \"o\": \"149.151\",\n    \"t\": \"Nov 21, 2017 8:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.1735\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.151\",\n    \"t\": \"Nov 21, 2017 8:48:00 AM\"\n  },\n  {\n    \"c\": \"149.1675\",\n    \"h\": \"149.177\",\n    \"l\": \"149.1565\",\n    \"o\": \"149.166\",\n    \"t\": \"Nov 21, 2017 8:49:00 AM\"\n  },\n  {\n    \"c\": \"149.175\",\n    \"h\": \"149.185\",\n    \"l\": \"149.1655\",\n    \"o\": \"149.1675\",\n    \"t\": \"Nov 21, 2017 8:50:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.1825\",\n    \"l\": \"149.159\",\n    \"o\": \"149.174\",\n    \"t\": \"Nov 21, 2017 8:51:00 AM\"\n  },\n  {\n    \"c\": \"149.184\",\n    \"h\": \"149.1845\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 8:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1815\",\n    \"h\": \"149.1845\",\n    \"l\": \"149.164\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 8:53:00 AM\"\n  },\n  {\n    \"c\": \"149.1575\",\n    \"h\": \"149.2005\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.182\",\n    \"t\": \"Nov 21, 2017 8:54:00 AM\"\n  },\n  {\n    \"c\": \"149.197\",\n    \"h\": \"149.198\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1585\",\n    \"t\": \"Nov 21, 2017 8:55:00 AM\"\n  },\n  {\n    \"c\": \"149.189\",\n    \"h\": \"149.198\",\n    \"l\": \"149.185\",\n    \"o\": \"149.1945\",\n    \"t\": \"Nov 21, 2017 8:56:00 AM\"\n  },\n  {\n    \"c\": \"149.18\",\n    \"h\": \"149.1895\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.1895\",\n    \"t\": \"Nov 21, 2017 8:57:00 AM\"\n  },\n  {\n    \"c\": \"149.158\",\n    \"h\": \"149.1785\",\n    \"l\": \"149.1505\",\n    \"o\": \"149.1785\",\n    \"t\": \"Nov 21, 2017 8:58:00 AM\"\n  },\n  {\n    \"c\": \"149.139\",\n    \"h\": \"149.1575\",\n    \"l\": \"149.128\",\n    \"o\": \"149.157\",\n    \"t\": \"Nov 21, 2017 8:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1095\",\n    \"h\": \"149.1385\",\n    \"l\": \"149.108\",\n    \"o\": \"149.1375\",\n    \"t\": \"Nov 21, 2017 9:00:00 AM\"\n  },\n  {\n    \"c\": \"149.1035\",\n    \"h\": \"149.1095\",\n    \"l\": \"149.098\",\n    \"o\": \"149.1095\",\n    \"t\": \"Nov 21, 2017 9:01:00 AM\"\n  },\n  {\n    \"c\": \"149.113\",\n    \"h\": \"149.113\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.1035\",\n    \"t\": \"Nov 21, 2017 9:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.1225\",\n    \"l\": \"149.1075\",\n    \"o\": \"149.1125\",\n    \"t\": \"Nov 21, 2017 9:03:00 AM\"\n  },\n  {\n    \"c\": \"149.1225\",\n    \"h\": \"149.1375\",\n    \"l\": \"149.114\",\n    \"o\": \"149.1145\",\n    \"t\": \"Nov 21, 2017 9:04:00 AM\"\n  },\n  {\n    \"c\": \"149.134\",\n    \"h\": \"149.1365\",\n    \"l\": \"149.118\",\n    \"o\": \"149.1235\",\n    \"t\": \"Nov 21, 2017 9:05:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.0975\",\n    \"o\": \"149.1345\",\n    \"t\": \"Nov 21, 2017 9:06:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.11\",\n    \"l\": \"149.1015\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 9:07:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.1045\",\n    \"l\": \"149.084\",\n    \"o\": \"149.1045\",\n    \"t\": \"Nov 21, 2017 9:08:00 AM\"\n  },\n  {\n    \"c\": \"149.092\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.088\",\n    \"o\": \"149.093\",\n    \"t\": \"Nov 21, 2017 9:09:00 AM\"\n  },\n  {\n    \"c\": \"149.071\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0615\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 9:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.064\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 9:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.0905\",\n    \"t\": \"Nov 21, 2017 9:12:00 AM\"\n  },\n  {\n    \"c\": \"149.1175\",\n    \"h\": \"149.122\",\n    \"l\": \"149.0895\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 9:13:00 AM\"\n  },\n  {\n    \"c\": \"149.133\",\n    \"h\": \"149.135\",\n    \"l\": \"149.1165\",\n    \"o\": \"149.1165\",\n    \"t\": \"Nov 21, 2017 9:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0975\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.0975\",\n    \"o\": \"149.1325\",\n    \"t\": \"Nov 21, 2017 9:15:00 AM\"\n  },\n  {\n    \"c\": \"149.098\",\n    \"h\": \"149.111\",\n    \"l\": \"149.091\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 9:16:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.106\",\n    \"l\": \"149.078\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 9:17:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.081\",\n    \"o\": \"149.0905\",\n    \"t\": \"Nov 21, 2017 9:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.09\",\n    \"l\": \"149.081\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 9:19:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.091\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0885\",\n    \"t\": \"Nov 21, 2017 9:20:00 AM\"\n  },\n  {\n    \"c\": \"149.094\",\n    \"h\": \"149.0995\",\n    \"l\": \"149.0755\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 9:21:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.0785\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 9:22:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.092\",\n    \"l\": \"149.075\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 9:23:00 AM\"\n  },\n  {\n    \"c\": \"149.0825\",\n    \"h\": \"149.0935\",\n    \"l\": \"149.074\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 9:24:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.082\",\n    \"l\": \"149.057\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 9:25:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.0745\",\n    \"l\": \"149.0395\",\n    \"o\": \"149.074\",\n    \"t\": \"Nov 21, 2017 9:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0145\",\n    \"h\": \"149.041\",\n    \"l\": \"149.012\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 9:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0085\",\n    \"h\": \"149.0235\",\n    \"l\": \"149.0065\",\n    \"o\": \"149.014\",\n    \"t\": \"Nov 21, 2017 9:28:00 AM\"\n  },\n  {\n    \"c\": \"149.0095\",\n    \"h\": \"149.0205\",\n    \"l\": \"149.005\",\n    \"o\": \"149.0095\",\n    \"t\": \"Nov 21, 2017 9:29:00 AM\"\n  },\n  {\n    \"c\": \"149.024\",\n    \"h\": \"149.05\",\n    \"l\": \"149.008\",\n    \"o\": \"149.008\",\n    \"t\": \"Nov 21, 2017 9:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0105\",\n    \"h\": \"149.0235\",\n    \"l\": \"148.9925\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 9:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.045\",\n    \"l\": \"149.01\",\n    \"o\": \"149.01\",\n    \"t\": \"Nov 21, 2017 9:32:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.045\",\n    \"l\": \"149.0295\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 9:33:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.0515\",\n    \"l\": \"149.03\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 9:34:00 AM\"\n  },\n  {\n    \"c\": \"149.05\",\n    \"h\": \"149.053\",\n    \"l\": \"149.038\",\n    \"o\": \"149.049\",\n    \"t\": \"Nov 21, 2017 9:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.056\",\n    \"l\": \"149.0465\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 9:36:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.054\",\n    \"l\": \"149.0415\",\n    \"o\": \"149.05\",\n    \"t\": \"Nov 21, 2017 9:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.071\",\n    \"l\": \"149.045\",\n    \"o\": \"149.051\",\n    \"t\": \"Nov 21, 2017 9:38:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.066\",\n    \"l\": \"149.051\",\n    \"o\": \"149.0515\",\n    \"t\": \"Nov 21, 2017 9:39:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.0695\",\n    \"l\": \"149.056\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 9:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0595\",\n    \"h\": \"149.0815\",\n    \"l\": \"149.0595\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 9:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.059\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 9:42:00 AM\"\n  },\n  {\n    \"c\": \"149.1075\",\n    \"h\": \"149.11\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 9:43:00 AM\"\n  },\n  {\n    \"c\": \"149.1035\",\n    \"h\": \"149.112\",\n    \"l\": \"149.0945\",\n    \"o\": \"149.108\",\n    \"t\": \"Nov 21, 2017 9:44:00 AM\"\n  },\n  {\n    \"c\": \"149.109\",\n    \"h\": \"149.1125\",\n    \"l\": \"149.0985\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 9:45:00 AM\"\n  },\n  {\n    \"c\": \"149.12\",\n    \"h\": \"149.121\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.1105\",\n    \"t\": \"Nov 21, 2017 9:46:00 AM\"\n  },\n  {\n    \"c\": \"149.1445\",\n    \"h\": \"149.1485\",\n    \"l\": \"149.1185\",\n    \"o\": \"149.12\",\n    \"t\": \"Nov 21, 2017 9:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.158\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 9:48:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.157\",\n    \"l\": \"149.138\",\n    \"o\": \"149.145\",\n    \"t\": \"Nov 21, 2017 9:49:00 AM\"\n  },\n  {\n    \"c\": \"149.1275\",\n    \"h\": \"149.152\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 9:50:00 AM\"\n  },\n  {\n    \"c\": \"149.119\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1275\",\n    \"t\": \"Nov 21, 2017 9:51:00 AM\"\n  },\n  {\n    \"c\": \"149.102\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.101\",\n    \"o\": \"149.1175\",\n    \"t\": \"Nov 21, 2017 9:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1175\",\n    \"h\": \"149.1175\",\n    \"l\": \"149.097\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 9:53:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.1175\",\n    \"l\": \"149.108\",\n    \"o\": \"149.117\",\n    \"t\": \"Nov 21, 2017 9:54:00 AM\"\n  },\n  {\n    \"c\": \"149.13\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.1155\",\n    \"t\": \"Nov 21, 2017 9:55:00 AM\"\n  },\n  {\n    \"c\": \"149.1335\",\n    \"h\": \"149.134\",\n    \"l\": \"149.121\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 9:56:00 AM\"\n  },\n  {\n    \"c\": \"149.1305\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.128\",\n    \"o\": \"149.1345\",\n    \"t\": \"Nov 21, 2017 9:57:00 AM\"\n  },\n  {\n    \"c\": \"149.1275\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 9:58:00 AM\"\n  },\n  {\n    \"c\": \"149.1255\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.1205\",\n    \"o\": \"149.128\",\n    \"t\": \"Nov 21, 2017 9:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1285\",\n    \"h\": \"149.1285\",\n    \"l\": \"149.115\",\n    \"o\": \"149.124\",\n    \"t\": \"Nov 21, 2017 10:00:00 AM\"\n  },\n  {\n    \"c\": \"149.121\",\n    \"h\": \"149.13\",\n    \"l\": \"149.1205\",\n    \"o\": \"149.1285\",\n    \"t\": \"Nov 21, 2017 10:01:00 AM\"\n  },\n  {\n    \"c\": \"149.135\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1195\",\n    \"o\": \"149.121\",\n    \"t\": \"Nov 21, 2017 10:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1355\",\n    \"h\": \"149.1415\",\n    \"l\": \"149.1315\",\n    \"o\": \"149.135\",\n    \"t\": \"Nov 21, 2017 10:03:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.156\",\n    \"l\": \"149.136\",\n    \"o\": \"149.136\",\n    \"t\": \"Nov 21, 2017 10:04:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.17\",\n    \"l\": \"149.1365\",\n    \"o\": \"149.144\",\n    \"t\": \"Nov 21, 2017 10:05:00 AM\"\n  },\n  {\n    \"c\": \"149.2005\",\n    \"h\": \"149.2005\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1585\",\n    \"t\": \"Nov 21, 2017 10:06:00 AM\"\n  },\n  {\n    \"c\": \"149.187\",\n    \"h\": \"149.202\",\n    \"l\": \"149.1865\",\n    \"o\": \"149.2005\",\n    \"t\": \"Nov 21, 2017 10:07:00 AM\"\n  },\n  {\n    \"c\": \"149.163\",\n    \"h\": \"149.188\",\n    \"l\": \"149.1605\",\n    \"o\": \"149.188\",\n    \"t\": \"Nov 21, 2017 10:08:00 AM\"\n  },\n  {\n    \"c\": \"149.152\",\n    \"h\": \"149.175\",\n    \"l\": \"149.147\",\n    \"o\": \"149.1635\",\n    \"t\": \"Nov 21, 2017 10:09:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1445\",\n    \"o\": \"149.1515\",\n    \"t\": \"Nov 21, 2017 10:10:00 AM\"\n  },\n  {\n    \"c\": \"149.1665\",\n    \"h\": \"149.1715\",\n    \"l\": \"149.148\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 10:11:00 AM\"\n  },\n  {\n    \"c\": \"149.182\",\n    \"h\": \"149.1885\",\n    \"l\": \"149.1645\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 10:12:00 AM\"\n  },\n  {\n    \"c\": \"149.1855\",\n    \"h\": \"149.187\",\n    \"l\": \"149.178\",\n    \"o\": \"149.1825\",\n    \"t\": \"Nov 21, 2017 10:13:00 AM\"\n  },\n  {\n    \"c\": \"149.1825\",\n    \"h\": \"149.1915\",\n    \"l\": \"149.18\",\n    \"o\": \"149.1855\",\n    \"t\": \"Nov 21, 2017 10:14:00 AM\"\n  },\n  {\n    \"c\": \"149.1685\",\n    \"h\": \"149.184\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 10:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.174\",\n    \"l\": \"149.159\",\n    \"o\": \"149.167\",\n    \"t\": \"Nov 21, 2017 10:16:00 AM\"\n  },\n  {\n    \"c\": \"149.167\",\n    \"h\": \"149.176\",\n    \"l\": \"149.1645\",\n    \"o\": \"149.166\",\n    \"t\": \"Nov 21, 2017 10:17:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1665\",\n    \"o\": \"149.167\",\n    \"t\": \"Nov 21, 2017 10:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1895\",\n    \"h\": \"149.202\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.176\",\n    \"t\": \"Nov 21, 2017 10:19:00 AM\"\n  },\n  {\n    \"c\": \"149.206\",\n    \"h\": \"149.208\",\n    \"l\": \"149.188\",\n    \"o\": \"149.1895\",\n    \"t\": \"Nov 21, 2017 10:20:00 AM\"\n  },\n  {\n    \"c\": \"149.198\",\n    \"h\": \"149.214\",\n    \"l\": \"149.1975\",\n    \"o\": \"149.2065\",\n    \"t\": \"Nov 21, 2017 10:21:00 AM\"\n  },\n  {\n    \"c\": \"149.1635\",\n    \"h\": \"149.1985\",\n    \"l\": \"149.1615\",\n    \"o\": \"149.1975\",\n    \"t\": \"Nov 21, 2017 10:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1685\",\n    \"h\": \"149.1725\",\n    \"l\": \"149.1595\",\n    \"o\": \"149.1625\",\n    \"t\": \"Nov 21, 2017 10:23:00 AM\"\n  },\n  {\n    \"c\": \"149.1665\",\n    \"h\": \"149.174\",\n    \"l\": \"149.163\",\n    \"o\": \"149.168\",\n    \"t\": \"Nov 21, 2017 10:24:00 AM\"\n  },\n  {\n    \"c\": \"149.161\",\n    \"h\": \"149.1725\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1665\",\n    \"t\": \"Nov 21, 2017 10:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1495\",\n    \"h\": \"149.1655\",\n    \"l\": \"149.146\",\n    \"o\": \"149.1615\",\n    \"t\": \"Nov 21, 2017 10:26:00 AM\"\n  },\n  {\n    \"c\": \"149.139\",\n    \"h\": \"149.1645\",\n    \"l\": \"149.139\",\n    \"o\": \"149.1495\",\n    \"t\": \"Nov 21, 2017 10:27:00 AM\"\n  },\n  {\n    \"c\": \"149.099\",\n    \"h\": \"149.139\",\n    \"l\": \"149.088\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 10:28:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.101\",\n    \"l\": \"149.089\",\n    \"o\": \"149.0995\",\n    \"t\": \"Nov 21, 2017 10:29:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.097\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.09\",\n    \"t\": \"Nov 21, 2017 10:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0995\",\n    \"h\": \"149.1055\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 10:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0865\",\n    \"h\": \"149.1035\",\n    \"l\": \"149.086\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 10:32:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 10:33:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.089\",\n    \"l\": \"149.048\",\n    \"o\": \"149.0845\",\n    \"t\": \"Nov 21, 2017 10:34:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.0685\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 10:35:00 AM\"\n  },\n  {\n    \"c\": \"149.068\",\n    \"h\": \"149.068\",\n    \"l\": \"149.0425\",\n    \"o\": \"149.05\",\n    \"t\": \"Nov 21, 2017 10:36:00 AM\"\n  },\n  {\n    \"c\": \"149.0545\",\n    \"h\": \"149.0765\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 10:37:00 AM\"\n  },\n  {\n    \"c\": \"149.081\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 10:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.084\",\n    \"l\": \"149.0685\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 10:39:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0695\",\n    \"o\": \"149.072\",\n    \"t\": \"Nov 21, 2017 10:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.091\",\n    \"t\": \"Nov 21, 2017 10:41:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.095\",\n    \"l\": \"149.077\",\n    \"o\": \"149.0805\",\n    \"t\": \"Nov 21, 2017 10:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0835\",\n    \"h\": \"149.096\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 10:43:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.091\",\n    \"l\": \"149.077\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 10:44:00 AM\"\n  },\n  {\n    \"c\": \"149.082\",\n    \"h\": \"149.089\",\n    \"l\": \"149.076\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 10:45:00 AM\"\n  },\n  {\n    \"c\": \"149.101\",\n    \"h\": \"149.104\",\n    \"l\": \"149.083\",\n    \"o\": \"149.084\",\n    \"t\": \"Nov 21, 2017 10:46:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.104\",\n    \"l\": \"149.083\",\n    \"o\": \"149.1\",\n    \"t\": \"Nov 21, 2017 10:47:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.092\",\n    \"l\": \"149.081\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:48:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.092\",\n    \"l\": \"149.08\",\n    \"o\": \"149.087\",\n    \"t\": \"Nov 21, 2017 10:49:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.088\",\n    \"l\": \"149.077\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 10:50:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.108\",\n    \"l\": \"149.077\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 10:51:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.111\",\n    \"l\": \"149.089\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 10:52:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.115\",\n    \"l\": \"149.093\",\n    \"o\": \"149.094\",\n    \"t\": \"Nov 21, 2017 10:53:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.117\",\n    \"l\": \"149.093\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 10:54:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.093\",\n    \"l\": \"149.08\",\n    \"o\": \"149.092\",\n    \"t\": \"Nov 21, 2017 10:55:00 AM\"\n  },\n  {\n    \"c\": \"149.073\",\n    \"h\": \"149.088\",\n    \"l\": \"149.064\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:56:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.087\",\n    \"l\": \"149.072\",\n    \"o\": \"149.072\",\n    \"t\": \"Nov 21, 2017 10:57:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.1\",\n    \"l\": \"149.082\",\n    \"o\": \"149.087\",\n    \"t\": \"Nov 21, 2017 10:58:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.086\",\n    \"l\": \"149.075\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:59:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.085\",\n    \"l\": \"149.07\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 11:00:00 AM\"\n  },\n  {\n    \"c\": \"149.082\",\n    \"h\": \"149.085\",\n    \"l\": \"149.073\",\n    \"o\": \"149.075\",\n    \"t\": \"Nov 21, 2017 11:01:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.097\",\n    \"l\": \"149.081\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 11:02:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.104\",\n    \"l\": \"149.08\",\n    \"o\": \"149.095\",\n    \"t\": \"Nov 21, 2017 11:03:00 AM\"\n  },\n  {\n    \"c\": \"149.081\",\n    \"h\": \"149.081\",\n    \"l\": \"149.079\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 11:04:00 AM\"\n  }\n]"
  },
  {
    "path": "app/src/main/assets/timesharing_backup.json",
    "content": "[\n  {\n    \"c\": \"148.942\",\n    \"h\": \"148.9445\",\n    \"l\": \"148.9245\",\n    \"o\": \"148.926\",\n    \"t\": \"Nov 21, 2017 2:45:00 AM\"\n  },\n  {\n    \"c\": \"148.9105\",\n    \"h\": \"148.9445\",\n    \"l\": \"148.9075\",\n    \"o\": \"148.942\",\n    \"t\": \"Nov 21, 2017 2:46:00 AM\"\n  },\n  {\n    \"c\": \"148.9175\",\n    \"h\": \"148.9175\",\n    \"l\": \"148.878\",\n    \"o\": \"148.906\",\n    \"t\": \"Nov 21, 2017 2:47:00 AM\"\n  },\n  {\n    \"c\": \"148.9155\",\n    \"h\": \"148.933\",\n    \"l\": \"148.905\",\n    \"o\": \"148.9175\",\n    \"t\": \"Nov 21, 2017 2:48:00 AM\"\n  },\n  {\n    \"c\": \"148.9035\",\n    \"h\": \"148.9195\",\n    \"l\": \"148.8955\",\n    \"o\": \"148.916\",\n    \"t\": \"Nov 21, 2017 2:49:00 AM\"\n  },\n  {\n    \"c\": \"148.9045\",\n    \"h\": \"148.9075\",\n    \"l\": \"148.8975\",\n    \"o\": \"148.9035\",\n    \"t\": \"Nov 21, 2017 2:50:00 AM\"\n  },\n  {\n    \"c\": \"148.9\",\n    \"h\": \"148.9045\",\n    \"l\": \"148.9\",\n    \"o\": \"148.9045\",\n    \"t\": \"Nov 21, 2017 2:51:00 AM\"\n  },\n  {\n    \"c\": \"148.9025\",\n    \"h\": \"148.908\",\n    \"l\": \"148.8915\",\n    \"o\": \"148.9005\",\n    \"t\": \"Nov 21, 2017 2:52:00 AM\"\n  },\n  {\n    \"c\": \"148.926\",\n    \"h\": \"148.926\",\n    \"l\": \"148.9015\",\n    \"o\": \"148.9015\",\n    \"t\": \"Nov 21, 2017 2:53:00 AM\"\n  },\n  {\n    \"c\": \"148.9105\",\n    \"h\": \"148.926\",\n    \"l\": \"148.91\",\n    \"o\": \"148.926\",\n    \"t\": \"Nov 21, 2017 2:54:00 AM\"\n  },\n  {\n    \"c\": \"148.9265\",\n    \"h\": \"148.941\",\n    \"l\": \"148.91\",\n    \"o\": \"148.91\",\n    \"t\": \"Nov 21, 2017 2:55:00 AM\"\n  },\n  {\n    \"c\": \"148.933\",\n    \"h\": \"148.9455\",\n    \"l\": \"148.9255\",\n    \"o\": \"148.9265\",\n    \"t\": \"Nov 21, 2017 2:56:00 AM\"\n  },\n  {\n    \"c\": \"148.94\",\n    \"h\": \"148.952\",\n    \"l\": \"148.932\",\n    \"o\": \"148.9325\",\n    \"t\": \"Nov 21, 2017 2:57:00 AM\"\n  },\n  {\n    \"c\": \"148.9325\",\n    \"h\": \"148.9465\",\n    \"l\": \"148.928\",\n    \"o\": \"148.94\",\n    \"t\": \"Nov 21, 2017 2:58:00 AM\"\n  },\n  {\n    \"c\": \"148.937\",\n    \"h\": \"148.9395\",\n    \"l\": \"148.913\",\n    \"o\": \"148.932\",\n    \"t\": \"Nov 21, 2017 2:59:00 AM\"\n  },\n  {\n    \"c\": \"148.9635\",\n    \"h\": \"148.9655\",\n    \"l\": \"148.937\",\n    \"o\": \"148.937\",\n    \"t\": \"Nov 21, 2017 3:00:00 AM\"\n  },\n  {\n    \"c\": \"148.973\",\n    \"h\": \"148.978\",\n    \"l\": \"148.962\",\n    \"o\": \"148.962\",\n    \"t\": \"Nov 21, 2017 3:01:00 AM\"\n  },\n  {\n    \"c\": \"148.9725\",\n    \"h\": \"148.976\",\n    \"l\": \"148.966\",\n    \"o\": \"148.9725\",\n    \"t\": \"Nov 21, 2017 3:02:00 AM\"\n  },\n  {\n    \"c\": \"148.975\",\n    \"h\": \"148.975\",\n    \"l\": \"148.965\",\n    \"o\": \"148.9725\",\n    \"t\": \"Nov 21, 2017 3:03:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.03\",\n    \"l\": \"148.9635\",\n    \"o\": \"148.976\",\n    \"t\": \"Nov 21, 2017 3:04:00 AM\"\n  },\n  {\n    \"c\": \"148.972\",\n    \"h\": \"149.093\",\n    \"l\": \"148.9695\",\n    \"o\": \"149.024\",\n    \"t\": \"Nov 21, 2017 3:05:00 AM\"\n  },\n  {\n    \"c\": \"148.981\",\n    \"h\": \"148.981\",\n    \"l\": \"148.9615\",\n    \"o\": \"148.973\",\n    \"t\": \"Nov 21, 2017 3:06:00 AM\"\n  },\n  {\n    \"c\": \"148.9825\",\n    \"h\": \"148.9885\",\n    \"l\": \"148.9755\",\n    \"o\": \"148.981\",\n    \"t\": \"Nov 21, 2017 3:07:00 AM\"\n  },\n  {\n    \"c\": \"148.9695\",\n    \"h\": \"148.994\",\n    \"l\": \"148.9665\",\n    \"o\": \"148.982\",\n    \"t\": \"Nov 21, 2017 3:08:00 AM\"\n  },\n  {\n    \"c\": \"148.9675\",\n    \"h\": \"148.9815\",\n    \"l\": \"148.9635\",\n    \"o\": \"148.97\",\n    \"t\": \"Nov 21, 2017 3:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0195\",\n    \"h\": \"149.0215\",\n    \"l\": \"148.963\",\n    \"o\": \"148.9675\",\n    \"t\": \"Nov 21, 2017 3:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.0355\",\n    \"l\": \"149.005\",\n    \"o\": \"149.0185\",\n    \"t\": \"Nov 21, 2017 3:11:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.036\",\n    \"t\": \"Nov 21, 2017 3:12:00 AM\"\n  },\n  {\n    \"c\": \"149.02\",\n    \"h\": \"149.0315\",\n    \"l\": \"149.016\",\n    \"o\": \"149.0295\",\n    \"t\": \"Nov 21, 2017 3:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.071\",\n    \"l\": \"149.0195\",\n    \"o\": \"149.0215\",\n    \"t\": \"Nov 21, 2017 3:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0655\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.032\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 3:15:00 AM\"\n  },\n  {\n    \"c\": \"149.065\",\n    \"h\": \"149.0795\",\n    \"l\": \"149.059\",\n    \"o\": \"149.0655\",\n    \"t\": \"Nov 21, 2017 3:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.09\",\n    \"l\": \"149.062\",\n    \"o\": \"149.0645\",\n    \"t\": \"Nov 21, 2017 3:17:00 AM\"\n  },\n  {\n    \"c\": \"149.078\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.06\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 3:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.086\",\n    \"l\": \"149.0755\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 3:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1755\",\n    \"l\": \"149.085\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 3:20:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.178\",\n    \"l\": \"149.103\",\n    \"o\": \"149.1735\",\n    \"t\": \"Nov 21, 2017 3:21:00 AM\"\n  },\n  {\n    \"c\": \"149.1395\",\n    \"h\": \"149.149\",\n    \"l\": \"149.1255\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 3:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1385\",\n    \"t\": \"Nov 21, 2017 3:23:00 AM\"\n  },\n  {\n    \"c\": \"149.157\",\n    \"h\": \"149.1615\",\n    \"l\": \"149.1475\",\n    \"o\": \"149.1595\",\n    \"t\": \"Nov 21, 2017 3:24:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.158\",\n    \"l\": \"149.131\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 3:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.157\",\n    \"l\": \"149.145\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 3:26:00 AM\"\n  },\n  {\n    \"c\": \"149.165\",\n    \"h\": \"149.171\",\n    \"l\": \"149.1475\",\n    \"o\": \"149.1485\",\n    \"t\": \"Nov 21, 2017 3:27:00 AM\"\n  },\n  {\n    \"c\": \"149.178\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1635\",\n    \"t\": \"Nov 21, 2017 3:28:00 AM\"\n  },\n  {\n    \"c\": \"149.19\",\n    \"h\": \"149.19\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.178\",\n    \"t\": \"Nov 21, 2017 3:29:00 AM\"\n  },\n  {\n    \"c\": \"149.1835\",\n    \"h\": \"149.198\",\n    \"l\": \"149.177\",\n    \"o\": \"149.191\",\n    \"t\": \"Nov 21, 2017 3:30:00 AM\"\n  },\n  {\n    \"c\": \"149.177\",\n    \"h\": \"149.187\",\n    \"l\": \"149.167\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 3:31:00 AM\"\n  },\n  {\n    \"c\": \"149.1725\",\n    \"h\": \"149.1855\",\n    \"l\": \"149.1685\",\n    \"o\": \"149.1775\",\n    \"t\": \"Nov 21, 2017 3:32:00 AM\"\n  },\n  {\n    \"c\": \"149.193\",\n    \"h\": \"149.195\",\n    \"l\": \"149.168\",\n    \"o\": \"149.1725\",\n    \"t\": \"Nov 21, 2017 3:33:00 AM\"\n  },\n  {\n    \"c\": \"149.191\",\n    \"h\": \"149.204\",\n    \"l\": \"149.1825\",\n    \"o\": \"149.1935\",\n    \"t\": \"Nov 21, 2017 3:34:00 AM\"\n  },\n  {\n    \"c\": \"149.195\",\n    \"h\": \"149.198\",\n    \"l\": \"149.1825\",\n    \"o\": \"149.1905\",\n    \"t\": \"Nov 21, 2017 3:35:00 AM\"\n  },\n  {\n    \"c\": \"149.197\",\n    \"h\": \"149.2395\",\n    \"l\": \"149.193\",\n    \"o\": \"149.196\",\n    \"t\": \"Nov 21, 2017 3:36:00 AM\"\n  },\n  {\n    \"c\": \"149.2235\",\n    \"h\": \"149.232\",\n    \"l\": \"149.193\",\n    \"o\": \"149.197\",\n    \"t\": \"Nov 21, 2017 3:37:00 AM\"\n  },\n  {\n    \"c\": \"149.2065\",\n    \"h\": \"149.2355\",\n    \"l\": \"149.2065\",\n    \"o\": \"149.224\",\n    \"t\": \"Nov 21, 2017 3:38:00 AM\"\n  },\n  {\n    \"c\": \"149.2145\",\n    \"h\": \"149.2185\",\n    \"l\": \"149.2075\",\n    \"o\": \"149.2075\",\n    \"t\": \"Nov 21, 2017 3:39:00 AM\"\n  },\n  {\n    \"c\": \"149.2075\",\n    \"h\": \"149.2145\",\n    \"l\": \"149.2045\",\n    \"o\": \"149.2145\",\n    \"t\": \"Nov 21, 2017 3:40:00 AM\"\n  },\n  {\n    \"c\": \"149.1765\",\n    \"h\": \"149.2125\",\n    \"l\": \"149.1765\",\n    \"o\": \"149.2085\",\n    \"t\": \"Nov 21, 2017 3:41:00 AM\"\n  },\n  {\n    \"c\": \"149.171\",\n    \"h\": \"149.189\",\n    \"l\": \"149.1655\",\n    \"o\": \"149.1775\",\n    \"t\": \"Nov 21, 2017 3:42:00 AM\"\n  },\n  {\n    \"c\": \"149.183\",\n    \"h\": \"149.188\",\n    \"l\": \"149.165\",\n    \"o\": \"149.171\",\n    \"t\": \"Nov 21, 2017 3:43:00 AM\"\n  },\n  {\n    \"c\": \"149.181\",\n    \"h\": \"149.1925\",\n    \"l\": \"149.1685\",\n    \"o\": \"149.183\",\n    \"t\": \"Nov 21, 2017 3:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1775\",\n    \"h\": \"149.192\",\n    \"l\": \"149.172\",\n    \"o\": \"149.179\",\n    \"t\": \"Nov 21, 2017 3:45:00 AM\"\n  },\n  {\n    \"c\": \"149.174\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1765\",\n    \"t\": \"Nov 21, 2017 3:46:00 AM\"\n  },\n  {\n    \"c\": \"149.17\",\n    \"h\": \"149.1885\",\n    \"l\": \"149.17\",\n    \"o\": \"149.1745\",\n    \"t\": \"Nov 21, 2017 3:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1805\",\n    \"l\": \"149.166\",\n    \"o\": \"149.1705\",\n    \"t\": \"Nov 21, 2017 3:48:00 AM\"\n  },\n  {\n    \"c\": \"149.1815\",\n    \"h\": \"149.1875\",\n    \"l\": \"149.1735\",\n    \"o\": \"149.1735\",\n    \"t\": \"Nov 21, 2017 3:49:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.181\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.1805\",\n    \"t\": \"Nov 21, 2017 3:50:00 AM\"\n  },\n  {\n    \"c\": \"149.1465\",\n    \"h\": \"149.162\",\n    \"l\": \"149.1455\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 3:51:00 AM\"\n  },\n  {\n    \"c\": \"149.1545\",\n    \"h\": \"149.1625\",\n    \"l\": \"149.141\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 3:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1405\",\n    \"h\": \"149.163\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1545\",\n    \"t\": \"Nov 21, 2017 3:53:00 AM\"\n  },\n  {\n    \"c\": \"149.148\",\n    \"h\": \"149.1505\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1405\",\n    \"t\": \"Nov 21, 2017 3:54:00 AM\"\n  },\n  {\n    \"c\": \"149.153\",\n    \"h\": \"149.156\",\n    \"l\": \"149.129\",\n    \"o\": \"149.148\",\n    \"t\": \"Nov 21, 2017 3:55:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.154\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1535\",\n    \"t\": \"Nov 21, 2017 3:56:00 AM\"\n  },\n  {\n    \"c\": \"149.163\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 3:57:00 AM\"\n  },\n  {\n    \"c\": \"149.166\",\n    \"h\": \"149.174\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.163\",\n    \"t\": \"Nov 21, 2017 3:58:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1435\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 3:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1245\",\n    \"h\": \"149.1515\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 4:00:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.1295\",\n    \"l\": \"149.115\",\n    \"o\": \"149.1245\",\n    \"t\": \"Nov 21, 2017 4:01:00 AM\"\n  },\n  {\n    \"c\": \"149.119\",\n    \"h\": \"149.125\",\n    \"l\": \"149.1145\",\n    \"o\": \"149.116\",\n    \"t\": \"Nov 21, 2017 4:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1325\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.11\",\n    \"o\": \"149.1185\",\n    \"t\": \"Nov 21, 2017 4:03:00 AM\"\n  },\n  {\n    \"c\": \"149.152\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1325\",\n    \"o\": \"149.1325\",\n    \"t\": \"Nov 21, 2017 4:04:00 AM\"\n  },\n  {\n    \"c\": \"149.161\",\n    \"h\": \"149.164\",\n    \"l\": \"149.152\",\n    \"o\": \"149.152\",\n    \"t\": \"Nov 21, 2017 4:05:00 AM\"\n  },\n  {\n    \"c\": \"149.1595\",\n    \"h\": \"149.169\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1615\",\n    \"t\": \"Nov 21, 2017 4:06:00 AM\"\n  },\n  {\n    \"c\": \"149.1475\",\n    \"h\": \"149.166\",\n    \"l\": \"149.144\",\n    \"o\": \"149.1595\",\n    \"t\": \"Nov 21, 2017 4:07:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.152\",\n    \"l\": \"149.137\",\n    \"o\": \"149.148\",\n    \"t\": \"Nov 21, 2017 4:08:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.1485\",\n    \"l\": \"149.1345\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 4:09:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.144\",\n    \"l\": \"149.1265\",\n    \"o\": \"149.137\",\n    \"t\": \"Nov 21, 2017 4:10:00 AM\"\n  },\n  {\n    \"c\": \"149.1485\",\n    \"h\": \"149.152\",\n    \"l\": \"149.1365\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 4:11:00 AM\"\n  },\n  {\n    \"c\": \"149.1355\",\n    \"h\": \"149.1475\",\n    \"l\": \"149.133\",\n    \"o\": \"149.1475\",\n    \"t\": \"Nov 21, 2017 4:12:00 AM\"\n  },\n  {\n    \"c\": \"149.116\",\n    \"h\": \"149.138\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1355\",\n    \"t\": \"Nov 21, 2017 4:13:00 AM\"\n  },\n  {\n    \"c\": \"149.13\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1165\",\n    \"t\": \"Nov 21, 2017 4:14:00 AM\"\n  },\n  {\n    \"c\": \"149.124\",\n    \"h\": \"149.13\",\n    \"l\": \"149.1195\",\n    \"o\": \"149.1295\",\n    \"t\": \"Nov 21, 2017 4:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1265\",\n    \"h\": \"149.1285\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.1245\",\n    \"t\": \"Nov 21, 2017 4:16:00 AM\"\n  },\n  {\n    \"c\": \"149.123\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.112\",\n    \"o\": \"149.128\",\n    \"t\": \"Nov 21, 2017 4:17:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.126\",\n    \"l\": \"149.109\",\n    \"o\": \"149.1225\",\n    \"t\": \"Nov 21, 2017 4:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1125\",\n    \"h\": \"149.123\",\n    \"l\": \"149.11\",\n    \"o\": \"149.1145\",\n    \"t\": \"Nov 21, 2017 4:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.117\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.112\",\n    \"t\": \"Nov 21, 2017 4:20:00 AM\"\n  },\n  {\n    \"c\": \"149.106\",\n    \"h\": \"149.115\",\n    \"l\": \"149.1045\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 4:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.105\",\n    \"l\": \"149.094\",\n    \"o\": \"149.1045\",\n    \"t\": \"Nov 21, 2017 4:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1195\",\n    \"h\": \"149.1195\",\n    \"l\": \"149.095\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 4:23:00 AM\"\n  },\n  {\n    \"c\": \"149.123\",\n    \"h\": \"149.1305\",\n    \"l\": \"149.115\",\n    \"o\": \"149.119\",\n    \"t\": \"Nov 21, 2017 4:24:00 AM\"\n  },\n  {\n    \"c\": \"149.134\",\n    \"h\": \"149.1355\",\n    \"l\": \"149.1215\",\n    \"o\": \"149.122\",\n    \"t\": \"Nov 21, 2017 4:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1215\",\n    \"h\": \"149.137\",\n    \"l\": \"149.12\",\n    \"o\": \"149.134\",\n    \"t\": \"Nov 21, 2017 4:26:00 AM\"\n  },\n  {\n    \"c\": \"149.1335\",\n    \"h\": \"149.137\",\n    \"l\": \"149.118\",\n    \"o\": \"149.1205\",\n    \"t\": \"Nov 21, 2017 4:27:00 AM\"\n  },\n  {\n    \"c\": \"149.144\",\n    \"h\": \"149.1525\",\n    \"l\": \"149.134\",\n    \"o\": \"149.134\",\n    \"t\": \"Nov 21, 2017 4:28:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.1585\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.1445\",\n    \"t\": \"Nov 21, 2017 4:29:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.151\",\n    \"l\": \"149.136\",\n    \"o\": \"149.1435\",\n    \"t\": \"Nov 21, 2017 4:30:00 AM\"\n  },\n  {\n    \"c\": \"149.114\",\n    \"h\": \"149.147\",\n    \"l\": \"149.114\",\n    \"o\": \"149.146\",\n    \"t\": \"Nov 21, 2017 4:31:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.1025\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 4:32:00 AM\"\n  },\n  {\n    \"c\": \"149.0985\",\n    \"h\": \"149.1115\",\n    \"l\": \"149.096\",\n    \"o\": \"149.1035\",\n    \"t\": \"Nov 21, 2017 4:33:00 AM\"\n  },\n  {\n    \"c\": \"149.0995\",\n    \"h\": \"149.1005\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 4:34:00 AM\"\n  },\n  {\n    \"c\": \"149.088\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 4:35:00 AM\"\n  },\n  {\n    \"c\": \"149.089\",\n    \"h\": \"149.089\",\n    \"l\": \"149.082\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 4:36:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.095\",\n    \"l\": \"149.0815\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 4:37:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 4:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0945\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.09\",\n    \"t\": \"Nov 21, 2017 4:39:00 AM\"\n  },\n  {\n    \"c\": \"149.098\",\n    \"h\": \"149.099\",\n    \"l\": \"149.0835\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 4:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0815\",\n    \"h\": \"149.0995\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.098\",\n    \"t\": \"Nov 21, 2017 4:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0875\",\n    \"h\": \"149.092\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 4:42:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 4:43:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.079\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 4:44:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.0795\",\n    \"t\": \"Nov 21, 2017 4:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.0715\",\n    \"o\": \"149.075\",\n    \"t\": \"Nov 21, 2017 4:46:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.079\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 4:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0835\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.077\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 4:48:00 AM\"\n  },\n  {\n    \"c\": \"149.0765\",\n    \"h\": \"149.083\",\n    \"l\": \"149.073\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 4:49:00 AM\"\n  },\n  {\n    \"c\": \"149.069\",\n    \"h\": \"149.078\",\n    \"l\": \"149.0665\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 4:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.076\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.07\",\n    \"t\": \"Nov 21, 2017 4:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0735\",\n    \"h\": \"149.076\",\n    \"l\": \"149.064\",\n    \"o\": \"149.0725\",\n    \"t\": \"Nov 21, 2017 4:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0675\",\n    \"h\": \"149.0735\",\n    \"l\": \"149.063\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 4:53:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.083\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.067\",\n    \"t\": \"Nov 21, 2017 4:54:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0645\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 4:55:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.0795\",\n    \"l\": \"149.061\",\n    \"o\": \"149.0785\",\n    \"t\": \"Nov 21, 2017 4:56:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.0655\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 4:57:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 4:58:00 AM\"\n  },\n  {\n    \"c\": \"149.031\",\n    \"h\": \"149.0545\",\n    \"l\": \"149.025\",\n    \"o\": \"149.043\",\n    \"t\": \"Nov 21, 2017 4:59:00 AM\"\n  },\n  {\n    \"c\": \"149.0095\",\n    \"h\": \"149.0455\",\n    \"l\": \"149.002\",\n    \"o\": \"149.0305\",\n    \"t\": \"Nov 21, 2017 5:00:00 AM\"\n  },\n  {\n    \"c\": \"149.007\",\n    \"h\": \"149.015\",\n    \"l\": \"149.0\",\n    \"o\": \"149.01\",\n    \"t\": \"Nov 21, 2017 5:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0045\",\n    \"h\": \"149.0095\",\n    \"l\": \"149.0\",\n    \"o\": \"149.008\",\n    \"t\": \"Nov 21, 2017 5:02:00 AM\"\n  },\n  {\n    \"c\": \"148.997\",\n    \"h\": \"149.0035\",\n    \"l\": \"148.9915\",\n    \"o\": \"149.0035\",\n    \"t\": \"Nov 21, 2017 5:03:00 AM\"\n  },\n  {\n    \"c\": \"148.989\",\n    \"h\": \"148.998\",\n    \"l\": \"148.985\",\n    \"o\": \"148.997\",\n    \"t\": \"Nov 21, 2017 5:04:00 AM\"\n  },\n  {\n    \"c\": \"148.9855\",\n    \"h\": \"149.0\",\n    \"l\": \"148.9825\",\n    \"o\": \"148.99\",\n    \"t\": \"Nov 21, 2017 5:05:00 AM\"\n  },\n  {\n    \"c\": \"148.977\",\n    \"h\": \"148.9935\",\n    \"l\": \"148.974\",\n    \"o\": \"148.986\",\n    \"t\": \"Nov 21, 2017 5:06:00 AM\"\n  },\n  {\n    \"c\": \"148.97\",\n    \"h\": \"148.9815\",\n    \"l\": \"148.961\",\n    \"o\": \"148.9765\",\n    \"t\": \"Nov 21, 2017 5:07:00 AM\"\n  },\n  {\n    \"c\": \"148.9865\",\n    \"h\": \"148.988\",\n    \"l\": \"148.9675\",\n    \"o\": \"148.9695\",\n    \"t\": \"Nov 21, 2017 5:08:00 AM\"\n  },\n  {\n    \"c\": \"149.002\",\n    \"h\": \"149.002\",\n    \"l\": \"148.9855\",\n    \"o\": \"148.9865\",\n    \"t\": \"Nov 21, 2017 5:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0085\",\n    \"h\": \"149.014\",\n    \"l\": \"148.9905\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:10:00 AM\"\n  },\n  {\n    \"c\": \"149.007\",\n    \"h\": \"149.0085\",\n    \"l\": \"148.9965\",\n    \"o\": \"149.0075\",\n    \"t\": \"Nov 21, 2017 5:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0185\",\n    \"h\": \"149.0185\",\n    \"l\": \"149.007\",\n    \"o\": \"149.007\",\n    \"t\": \"Nov 21, 2017 5:12:00 AM\"\n  },\n  {\n    \"c\": \"149.0165\",\n    \"h\": \"149.0215\",\n    \"l\": \"149.0135\",\n    \"o\": \"149.0185\",\n    \"t\": \"Nov 21, 2017 5:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0305\",\n    \"h\": \"149.033\",\n    \"l\": \"149.0145\",\n    \"o\": \"149.0175\",\n    \"t\": \"Nov 21, 2017 5:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0365\",\n    \"h\": \"149.0375\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.03\",\n    \"t\": \"Nov 21, 2017 5:15:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.04\",\n    \"l\": \"149.033\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 5:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.047\",\n    \"l\": \"149.0375\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 5:17:00 AM\"\n  },\n  {\n    \"c\": \"149.0455\",\n    \"h\": \"149.051\",\n    \"l\": \"149.038\",\n    \"o\": \"149.0405\",\n    \"t\": \"Nov 21, 2017 5:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0535\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0455\",\n    \"o\": \"149.0455\",\n    \"t\": \"Nov 21, 2017 5:19:00 AM\"\n  },\n  {\n    \"c\": \"149.055\",\n    \"h\": \"149.059\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 5:20:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.0455\",\n    \"o\": \"149.055\",\n    \"t\": \"Nov 21, 2017 5:21:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0495\",\n    \"o\": \"149.0635\",\n    \"t\": \"Nov 21, 2017 5:22:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.051\",\n    \"t\": \"Nov 21, 2017 5:23:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0645\",\n    \"l\": \"149.046\",\n    \"o\": \"149.0645\",\n    \"t\": \"Nov 21, 2017 5:24:00 AM\"\n  },\n  {\n    \"c\": \"149.0645\",\n    \"h\": \"149.0645\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.056\",\n    \"t\": \"Nov 21, 2017 5:25:00 AM\"\n  },\n  {\n    \"c\": \"149.076\",\n    \"h\": \"149.077\",\n    \"l\": \"149.063\",\n    \"o\": \"149.063\",\n    \"t\": \"Nov 21, 2017 5:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0805\",\n    \"l\": \"149.0725\",\n    \"o\": \"149.0755\",\n    \"t\": \"Nov 21, 2017 5:27:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.087\",\n    \"l\": \"149.08\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 5:28:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.084\",\n    \"t\": \"Nov 21, 2017 5:29:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 5:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0975\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 5:31:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.1015\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 5:32:00 AM\"\n  },\n  {\n    \"c\": \"149.107\",\n    \"h\": \"149.1095\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.0835\",\n    \"t\": \"Nov 21, 2017 5:33:00 AM\"\n  },\n  {\n    \"c\": \"149.1025\",\n    \"h\": \"149.113\",\n    \"l\": \"149.095\",\n    \"o\": \"149.1055\",\n    \"t\": \"Nov 21, 2017 5:34:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.1035\",\n    \"l\": \"149.0935\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 5:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.097\",\n    \"l\": \"149.091\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 5:36:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0835\",\n    \"o\": \"149.0925\",\n    \"t\": \"Nov 21, 2017 5:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0755\",\n    \"h\": \"149.087\",\n    \"l\": \"149.0675\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 5:38:00 AM\"\n  },\n  {\n    \"c\": \"149.05\",\n    \"h\": \"149.078\",\n    \"l\": \"149.0495\",\n    \"o\": \"149.0765\",\n    \"t\": \"Nov 21, 2017 5:39:00 AM\"\n  },\n  {\n    \"c\": \"149.018\",\n    \"h\": \"149.051\",\n    \"l\": \"149.0155\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 5:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0365\",\n    \"h\": \"149.037\",\n    \"l\": \"149.0175\",\n    \"o\": \"149.018\",\n    \"t\": \"Nov 21, 2017 5:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.0375\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 5:42:00 AM\"\n  },\n  {\n    \"c\": \"149.057\",\n    \"h\": \"149.07\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 5:43:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.064\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0575\",\n    \"t\": \"Nov 21, 2017 5:44:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.074\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.0655\",\n    \"t\": \"Nov 21, 2017 5:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.084\",\n    \"l\": \"149.0725\",\n    \"o\": \"149.0735\",\n    \"t\": \"Nov 21, 2017 5:46:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.08\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 5:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0685\",\n    \"h\": \"149.0775\",\n    \"l\": \"149.068\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 5:48:00 AM\"\n  },\n  {\n    \"c\": \"149.067\",\n    \"h\": \"149.0685\",\n    \"l\": \"149.066\",\n    \"o\": \"149.067\",\n    \"t\": \"Nov 21, 2017 5:49:00 AM\"\n  },\n  {\n    \"c\": \"149.045\",\n    \"h\": \"149.073\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.066\",\n    \"t\": \"Nov 21, 2017 5:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.046\",\n    \"l\": \"149.0225\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 5:51:00 AM\"\n  },\n  {\n    \"c\": \"149.004\",\n    \"h\": \"149.023\",\n    \"l\": \"149.004\",\n    \"o\": \"149.023\",\n    \"t\": \"Nov 21, 2017 5:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0175\",\n    \"h\": \"149.022\",\n    \"l\": \"149.0045\",\n    \"o\": \"149.0045\",\n    \"t\": \"Nov 21, 2017 5:53:00 AM\"\n  },\n  {\n    \"c\": \"149.011\",\n    \"h\": \"149.0195\",\n    \"l\": \"149.008\",\n    \"o\": \"149.0175\",\n    \"t\": \"Nov 21, 2017 5:54:00 AM\"\n  },\n  {\n    \"c\": \"149.009\",\n    \"h\": \"149.0115\",\n    \"l\": \"149.001\",\n    \"o\": \"149.0115\",\n    \"t\": \"Nov 21, 2017 5:55:00 AM\"\n  },\n  {\n    \"c\": \"149.001\",\n    \"h\": \"149.0155\",\n    \"l\": \"148.9975\",\n    \"o\": \"149.007\",\n    \"t\": \"Nov 21, 2017 5:56:00 AM\"\n  },\n  {\n    \"c\": \"149.0025\",\n    \"h\": \"149.005\",\n    \"l\": \"148.998\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:57:00 AM\"\n  },\n  {\n    \"c\": \"149.041\",\n    \"h\": \"149.0555\",\n    \"l\": \"149.0025\",\n    \"o\": \"149.0025\",\n    \"t\": \"Nov 21, 2017 5:58:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.069\",\n    \"l\": \"149.033\",\n    \"o\": \"149.042\",\n    \"t\": \"Nov 21, 2017 5:59:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.0805\",\n    \"l\": \"149.0405\",\n    \"o\": \"149.0805\",\n    \"t\": \"Nov 21, 2017 6:00:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.039\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 6:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0415\",\n    \"h\": \"149.0415\",\n    \"l\": \"149.0355\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:02:00 AM\"\n  },\n  {\n    \"c\": \"149.0635\",\n    \"h\": \"149.0635\",\n    \"l\": \"149.0415\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 6:03:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.1045\",\n    \"l\": \"149.064\",\n    \"o\": \"149.064\",\n    \"t\": \"Nov 21, 2017 6:04:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.105\",\n    \"l\": \"149.0915\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 6:05:00 AM\"\n  },\n  {\n    \"c\": \"149.0815\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0925\",\n    \"t\": \"Nov 21, 2017 6:06:00 AM\"\n  },\n  {\n    \"c\": \"149.0875\",\n    \"h\": \"149.0885\",\n    \"l\": \"149.082\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 6:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0925\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:08:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.093\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.0945\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0935\",\n    \"t\": \"Nov 21, 2017 6:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.088\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:11:00 AM\"\n  },\n  {\n    \"c\": \"149.097\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0945\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 6:12:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0965\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:13:00 AM\"\n  },\n  {\n    \"c\": \"149.0965\",\n    \"h\": \"149.097\",\n    \"l\": \"149.0965\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:14:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.092\",\n    \"o\": \"149.095\",\n    \"t\": \"Nov 21, 2017 6:15:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.099\",\n    \"l\": \"149.094\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 6:16:00 AM\"\n  },\n  {\n    \"c\": \"149.0915\",\n    \"h\": \"149.0965\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 6:17:00 AM\"\n  },\n  {\n    \"c\": \"149.1015\",\n    \"h\": \"149.102\",\n    \"l\": \"149.0885\",\n    \"o\": \"149.091\",\n    \"t\": \"Nov 21, 2017 6:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0955\",\n    \"h\": \"149.107\",\n    \"l\": \"149.0905\",\n    \"o\": \"149.1005\",\n    \"t\": \"Nov 21, 2017 6:19:00 AM\"\n  },\n  {\n    \"c\": \"149.0935\",\n    \"h\": \"149.105\",\n    \"l\": \"149.0905\",\n    \"o\": \"149.0965\",\n    \"t\": \"Nov 21, 2017 6:20:00 AM\"\n  },\n  {\n    \"c\": \"149.096\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.094\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 6:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0925\",\n    \"h\": \"149.096\",\n    \"l\": \"149.0925\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 6:22:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0855\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:23:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.09\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:24:00 AM\"\n  },\n  {\n    \"c\": \"149.088\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.087\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:25:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.0875\",\n    \"l\": \"149.084\",\n    \"o\": \"149.0875\",\n    \"t\": \"Nov 21, 2017 6:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.0635\",\n    \"o\": \"149.0825\",\n    \"t\": \"Nov 21, 2017 6:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.0865\",\n    \"l\": \"149.078\",\n    \"o\": \"149.0795\",\n    \"t\": \"Nov 21, 2017 6:28:00 AM\"\n  },\n  {\n    \"c\": \"149.065\",\n    \"h\": \"149.0885\",\n    \"l\": \"149.062\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 6:29:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.065\",\n    \"l\": \"149.052\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 6:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.094\",\n    \"l\": \"149.061\",\n    \"o\": \"149.0625\",\n    \"t\": \"Nov 21, 2017 6:31:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 6:32:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.088\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 6:33:00 AM\"\n  },\n  {\n    \"c\": \"149.089\",\n    \"h\": \"149.0925\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.088\",\n    \"t\": \"Nov 21, 2017 6:34:00 AM\"\n  },\n  {\n    \"c\": \"149.0865\",\n    \"h\": \"149.095\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.0895\",\n    \"t\": \"Nov 21, 2017 6:35:00 AM\"\n  },\n  {\n    \"c\": \"149.097\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0865\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 6:36:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0875\",\n    \"o\": \"149.0975\",\n    \"t\": \"Nov 21, 2017 6:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.095\",\n    \"l\": \"149.067\",\n    \"o\": \"149.092\",\n    \"t\": \"Nov 21, 2017 6:38:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.0815\",\n    \"l\": \"149.074\",\n    \"o\": \"149.074\",\n    \"t\": \"Nov 21, 2017 6:39:00 AM\"\n  },\n  {\n    \"c\": \"149.0775\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 6:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0785\",\n    \"h\": \"149.08\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.077\",\n    \"t\": \"Nov 21, 2017 6:41:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.081\",\n    \"l\": \"149.0765\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 6:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0765\",\n    \"h\": \"149.0785\",\n    \"l\": \"149.076\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 6:43:00 AM\"\n  },\n  {\n    \"c\": \"149.075\",\n    \"h\": \"149.0765\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.076\",\n    \"t\": \"Nov 21, 2017 6:44:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0745\",\n    \"l\": \"149.053\",\n    \"o\": \"149.0745\",\n    \"t\": \"Nov 21, 2017 6:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0375\",\n    \"h\": \"149.0585\",\n    \"l\": \"149.0355\",\n    \"o\": \"149.0555\",\n    \"t\": \"Nov 21, 2017 6:46:00 AM\"\n  },\n  {\n    \"c\": \"149.0415\",\n    \"h\": \"149.0425\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.0395\",\n    \"t\": \"Nov 21, 2017 6:47:00 AM\"\n  },\n  {\n    \"c\": \"149.0445\",\n    \"h\": \"149.045\",\n    \"l\": \"149.04\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:48:00 AM\"\n  },\n  {\n    \"c\": \"149.059\",\n    \"h\": \"149.06\",\n    \"l\": \"149.045\",\n    \"o\": \"149.0455\",\n    \"t\": \"Nov 21, 2017 6:49:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.059\",\n    \"l\": \"149.049\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 6:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.054\",\n    \"l\": \"149.05\",\n    \"o\": \"149.0515\",\n    \"t\": \"Nov 21, 2017 6:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.052\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.052\",\n    \"t\": \"Nov 21, 2017 6:52:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.0475\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 6:53:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.04\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 6:54:00 AM\"\n  },\n  {\n    \"c\": \"149.0345\",\n    \"h\": \"149.04\",\n    \"l\": \"149.034\",\n    \"o\": \"149.0385\",\n    \"t\": \"Nov 21, 2017 6:55:00 AM\"\n  },\n  {\n    \"c\": \"149.0405\",\n    \"h\": \"149.045\",\n    \"l\": \"149.034\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 6:56:00 AM\"\n  },\n  {\n    \"c\": \"149.0245\",\n    \"h\": \"149.0425\",\n    \"l\": \"149.022\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 6:57:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.037\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 6:58:00 AM\"\n  },\n  {\n    \"c\": \"149.0235\",\n    \"h\": \"149.0285\",\n    \"l\": \"149.015\",\n    \"o\": \"149.0285\",\n    \"t\": \"Nov 21, 2017 6:59:00 AM\"\n  },\n  {\n    \"c\": \"149.032\",\n    \"h\": \"149.033\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 7:00:00 AM\"\n  },\n  {\n    \"c\": \"149.025\",\n    \"h\": \"149.035\",\n    \"l\": \"149.022\",\n    \"o\": \"149.031\",\n    \"t\": \"Nov 21, 2017 7:01:00 AM\"\n  },\n  {\n    \"c\": \"149.0245\",\n    \"h\": \"149.029\",\n    \"l\": \"149.011\",\n    \"o\": \"149.0245\",\n    \"t\": \"Nov 21, 2017 7:02:00 AM\"\n  },\n  {\n    \"c\": \"149.019\",\n    \"h\": \"149.029\",\n    \"l\": \"149.0135\",\n    \"o\": \"149.026\",\n    \"t\": \"Nov 21, 2017 7:03:00 AM\"\n  },\n  {\n    \"c\": \"149.011\",\n    \"h\": \"149.02\",\n    \"l\": \"149.011\",\n    \"o\": \"149.02\",\n    \"t\": \"Nov 21, 2017 7:04:00 AM\"\n  },\n  {\n    \"c\": \"149.0035\",\n    \"h\": \"149.0165\",\n    \"l\": \"148.9985\",\n    \"o\": \"149.012\",\n    \"t\": \"Nov 21, 2017 7:05:00 AM\"\n  },\n  {\n    \"c\": \"149.012\",\n    \"h\": \"149.012\",\n    \"l\": \"148.9965\",\n    \"o\": \"149.0045\",\n    \"t\": \"Nov 21, 2017 7:06:00 AM\"\n  },\n  {\n    \"c\": \"148.989\",\n    \"h\": \"149.014\",\n    \"l\": \"148.987\",\n    \"o\": \"149.0115\",\n    \"t\": \"Nov 21, 2017 7:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0215\",\n    \"h\": \"149.0225\",\n    \"l\": \"148.991\",\n    \"o\": \"148.991\",\n    \"t\": \"Nov 21, 2017 7:08:00 AM\"\n  },\n  {\n    \"c\": \"149.0195\",\n    \"h\": \"149.024\",\n    \"l\": \"149.019\",\n    \"o\": \"149.019\",\n    \"t\": \"Nov 21, 2017 7:09:00 AM\"\n  },\n  {\n    \"c\": \"149.024\",\n    \"h\": \"149.0255\",\n    \"l\": \"149.017\",\n    \"o\": \"149.018\",\n    \"t\": \"Nov 21, 2017 7:10:00 AM\"\n  },\n  {\n    \"c\": \"149.052\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.02\",\n    \"o\": \"149.0225\",\n    \"t\": \"Nov 21, 2017 7:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0485\",\n    \"h\": \"149.0545\",\n    \"l\": \"149.048\",\n    \"o\": \"149.052\",\n    \"t\": \"Nov 21, 2017 7:12:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.048\",\n    \"l\": \"149.041\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:13:00 AM\"\n  },\n  {\n    \"c\": \"149.039\",\n    \"h\": \"149.043\",\n    \"l\": \"149.0385\",\n    \"o\": \"149.043\",\n    \"t\": \"Nov 21, 2017 7:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0335\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.0305\",\n    \"o\": \"149.039\",\n    \"t\": \"Nov 21, 2017 7:15:00 AM\"\n  },\n  {\n    \"c\": \"149.0285\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.027\",\n    \"o\": \"149.0325\",\n    \"t\": \"Nov 21, 2017 7:16:00 AM\"\n  },\n  {\n    \"c\": \"149.027\",\n    \"h\": \"149.03\",\n    \"l\": \"149.0225\",\n    \"o\": \"149.0285\",\n    \"t\": \"Nov 21, 2017 7:17:00 AM\"\n  },\n  {\n    \"c\": \"149.0295\",\n    \"h\": \"149.03\",\n    \"l\": \"149.019\",\n    \"o\": \"149.0265\",\n    \"t\": \"Nov 21, 2017 7:18:00 AM\"\n  },\n  {\n    \"c\": \"149.031\",\n    \"h\": \"149.031\",\n    \"l\": \"149.027\",\n    \"o\": \"149.0295\",\n    \"t\": \"Nov 21, 2017 7:19:00 AM\"\n  },\n  {\n    \"c\": \"149.028\",\n    \"h\": \"149.031\",\n    \"l\": \"149.028\",\n    \"o\": \"149.029\",\n    \"t\": \"Nov 21, 2017 7:20:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.0375\",\n    \"l\": \"149.0265\",\n    \"o\": \"149.027\",\n    \"t\": \"Nov 21, 2017 7:21:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.043\",\n    \"l\": \"149.0325\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 7:22:00 AM\"\n  },\n  {\n    \"c\": \"149.0355\",\n    \"h\": \"149.037\",\n    \"l\": \"149.0285\",\n    \"o\": \"149.037\",\n    \"t\": \"Nov 21, 2017 7:23:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0395\",\n    \"l\": \"149.033\",\n    \"o\": \"149.033\",\n    \"t\": \"Nov 21, 2017 7:24:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.03\",\n    \"o\": \"149.033\",\n    \"t\": \"Nov 21, 2017 7:25:00 AM\"\n  },\n  {\n    \"c\": \"149.033\",\n    \"h\": \"149.0345\",\n    \"l\": \"149.033\",\n    \"o\": \"149.0345\",\n    \"t\": \"Nov 21, 2017 7:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0435\",\n    \"l\": \"149.032\",\n    \"o\": \"149.0325\",\n    \"t\": \"Nov 21, 2017 7:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0465\",\n    \"h\": \"149.05\",\n    \"l\": \"149.0425\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:28:00 AM\"\n  },\n  {\n    \"c\": \"149.0475\",\n    \"h\": \"149.0485\",\n    \"l\": \"149.0465\",\n    \"o\": \"149.047\",\n    \"t\": \"Nov 21, 2017 7:29:00 AM\"\n  },\n  {\n    \"c\": \"149.056\",\n    \"h\": \"149.0595\",\n    \"l\": \"149.048\",\n    \"o\": \"149.048\",\n    \"t\": \"Nov 21, 2017 7:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0595\",\n    \"h\": \"149.06\",\n    \"l\": \"149.057\",\n    \"o\": \"149.057\",\n    \"t\": \"Nov 21, 2017 7:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0605\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.056\",\n    \"o\": \"149.058\",\n    \"t\": \"Nov 21, 2017 7:32:00 AM\"\n  },\n  {\n    \"c\": \"149.067\",\n    \"h\": \"149.07\",\n    \"l\": \"149.059\",\n    \"o\": \"149.062\",\n    \"t\": \"Nov 21, 2017 7:33:00 AM\"\n  },\n  {\n    \"c\": \"149.063\",\n    \"h\": \"149.075\",\n    \"l\": \"149.063\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 7:34:00 AM\"\n  },\n  {\n    \"c\": \"149.062\",\n    \"h\": \"149.065\",\n    \"l\": \"149.0615\",\n    \"o\": \"149.0635\",\n    \"t\": \"Nov 21, 2017 7:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0625\",\n    \"h\": \"149.063\",\n    \"l\": \"149.061\",\n    \"o\": \"149.061\",\n    \"t\": \"Nov 21, 2017 7:36:00 AM\"\n  },\n  {\n    \"c\": \"149.06\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.056\",\n    \"o\": \"149.062\",\n    \"t\": \"Nov 21, 2017 7:37:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.085\",\n    \"l\": \"149.059\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 7:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.085\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 7:39:00 AM\"\n  },\n  {\n    \"c\": \"149.0705\",\n    \"h\": \"149.0735\",\n    \"l\": \"149.0685\",\n    \"o\": \"149.073\",\n    \"t\": \"Nov 21, 2017 7:40:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.074\",\n    \"l\": \"149.0635\",\n    \"o\": \"149.07\",\n    \"t\": \"Nov 21, 2017 7:41:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.077\",\n    \"l\": \"149.058\",\n    \"o\": \"149.0665\",\n    \"t\": \"Nov 21, 2017 7:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0705\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.066\",\n    \"o\": \"149.077\",\n    \"t\": \"Nov 21, 2017 7:43:00 AM\"\n  },\n  {\n    \"c\": \"149.059\",\n    \"h\": \"149.0775\",\n    \"l\": \"149.058\",\n    \"o\": \"149.071\",\n    \"t\": \"Nov 21, 2017 7:44:00 AM\"\n  },\n  {\n    \"c\": \"149.077\",\n    \"h\": \"149.08\",\n    \"l\": \"149.052\",\n    \"o\": \"149.0595\",\n    \"t\": \"Nov 21, 2017 7:45:00 AM\"\n  },\n  {\n    \"c\": \"149.0605\",\n    \"h\": \"149.077\",\n    \"l\": \"149.0605\",\n    \"o\": \"149.0765\",\n    \"t\": \"Nov 21, 2017 7:46:00 AM\"\n  },\n  {\n    \"c\": \"149.044\",\n    \"h\": \"149.0605\",\n    \"l\": \"149.038\",\n    \"o\": \"149.06\",\n    \"t\": \"Nov 21, 2017 7:47:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.063\",\n    \"l\": \"149.0445\",\n    \"o\": \"149.0445\",\n    \"t\": \"Nov 21, 2017 7:48:00 AM\"\n  },\n  {\n    \"c\": \"149.06\",\n    \"h\": \"149.06\",\n    \"l\": \"149.048\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 7:49:00 AM\"\n  },\n  {\n    \"c\": \"149.058\",\n    \"h\": \"149.0625\",\n    \"l\": \"149.0565\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 7:50:00 AM\"\n  },\n  {\n    \"c\": \"149.0555\",\n    \"h\": \"149.0615\",\n    \"l\": \"149.0555\",\n    \"o\": \"149.058\",\n    \"t\": \"Nov 21, 2017 7:51:00 AM\"\n  },\n  {\n    \"c\": \"149.0125\",\n    \"h\": \"149.056\",\n    \"l\": \"149.0125\",\n    \"o\": \"149.054\",\n    \"t\": \"Nov 21, 2017 7:52:00 AM\"\n  },\n  {\n    \"c\": \"149.0165\",\n    \"h\": \"149.02\",\n    \"l\": \"149.0015\",\n    \"o\": \"149.0135\",\n    \"t\": \"Nov 21, 2017 7:53:00 AM\"\n  },\n  {\n    \"c\": \"149.026\",\n    \"h\": \"149.0335\",\n    \"l\": \"149.007\",\n    \"o\": \"149.0145\",\n    \"t\": \"Nov 21, 2017 7:54:00 AM\"\n  },\n  {\n    \"c\": \"149.03\",\n    \"h\": \"149.0355\",\n    \"l\": \"149.0235\",\n    \"o\": \"149.0255\",\n    \"t\": \"Nov 21, 2017 7:55:00 AM\"\n  },\n  {\n    \"c\": \"149.036\",\n    \"h\": \"149.0495\",\n    \"l\": \"149.0305\",\n    \"o\": \"149.0305\",\n    \"t\": \"Nov 21, 2017 7:56:00 AM\"\n  },\n  {\n    \"c\": \"149.041\",\n    \"h\": \"149.042\",\n    \"l\": \"149.036\",\n    \"o\": \"149.0375\",\n    \"t\": \"Nov 21, 2017 7:57:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.0535\",\n    \"l\": \"149.0405\",\n    \"o\": \"149.042\",\n    \"t\": \"Nov 21, 2017 7:58:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.052\",\n    \"l\": \"149.043\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 7:59:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.0565\",\n    \"l\": \"149.032\",\n    \"o\": \"149.047\",\n    \"t\": \"Nov 21, 2017 8:00:00 AM\"\n  },\n  {\n    \"c\": \"149.0855\",\n    \"h\": \"149.096\",\n    \"l\": \"149.036\",\n    \"o\": \"149.0425\",\n    \"t\": \"Nov 21, 2017 8:01:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.104\",\n    \"l\": \"149.0795\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 8:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1095\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.083\",\n    \"o\": \"149.104\",\n    \"t\": \"Nov 21, 2017 8:03:00 AM\"\n  },\n  {\n    \"c\": \"149.126\",\n    \"h\": \"149.1395\",\n    \"l\": \"149.109\",\n    \"o\": \"149.11\",\n    \"t\": \"Nov 21, 2017 8:04:00 AM\"\n  },\n  {\n    \"c\": \"149.127\",\n    \"h\": \"149.141\",\n    \"l\": \"149.123\",\n    \"o\": \"149.1255\",\n    \"t\": \"Nov 21, 2017 8:05:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.138\",\n    \"l\": \"149.112\",\n    \"o\": \"149.126\",\n    \"t\": \"Nov 21, 2017 8:06:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.1185\",\n    \"l\": \"149.078\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 8:07:00 AM\"\n  },\n  {\n    \"c\": \"149.0825\",\n    \"h\": \"149.0875\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 8:08:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.0665\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 8:09:00 AM\"\n  },\n  {\n    \"c\": \"149.0545\",\n    \"h\": \"149.076\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.0745\",\n    \"t\": \"Nov 21, 2017 8:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0685\",\n    \"h\": \"149.0695\",\n    \"l\": \"149.0525\",\n    \"o\": \"149.053\",\n    \"t\": \"Nov 21, 2017 8:11:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.1025\",\n    \"l\": \"149.063\",\n    \"o\": \"149.068\",\n    \"t\": \"Nov 21, 2017 8:12:00 AM\"\n  },\n  {\n    \"c\": \"149.116\",\n    \"h\": \"149.1195\",\n    \"l\": \"149.0935\",\n    \"o\": \"149.0935\",\n    \"t\": \"Nov 21, 2017 8:13:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.1155\",\n    \"l\": \"149.103\",\n    \"o\": \"149.1155\",\n    \"t\": \"Nov 21, 2017 8:14:00 AM\"\n  },\n  {\n    \"c\": \"149.1065\",\n    \"h\": \"149.124\",\n    \"l\": \"149.099\",\n    \"o\": \"149.1025\",\n    \"t\": \"Nov 21, 2017 8:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1125\",\n    \"h\": \"149.1135\",\n    \"l\": \"149.1005\",\n    \"o\": \"149.1075\",\n    \"t\": \"Nov 21, 2017 8:16:00 AM\"\n  },\n  {\n    \"c\": \"149.1295\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1125\",\n    \"o\": \"149.1125\",\n    \"t\": \"Nov 21, 2017 8:17:00 AM\"\n  },\n  {\n    \"c\": \"149.135\",\n    \"h\": \"149.1375\",\n    \"l\": \"149.1225\",\n    \"o\": \"149.1285\",\n    \"t\": \"Nov 21, 2017 8:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1375\",\n    \"h\": \"149.1395\",\n    \"l\": \"149.1325\",\n    \"o\": \"149.135\",\n    \"t\": \"Nov 21, 2017 8:19:00 AM\"\n  },\n  {\n    \"c\": \"149.1615\",\n    \"h\": \"149.17\",\n    \"l\": \"149.1375\",\n    \"o\": \"149.1375\",\n    \"t\": \"Nov 21, 2017 8:20:00 AM\"\n  },\n  {\n    \"c\": \"149.1415\",\n    \"h\": \"149.173\",\n    \"l\": \"149.141\",\n    \"o\": \"149.162\",\n    \"t\": \"Nov 21, 2017 8:21:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.153\",\n    \"l\": \"149.137\",\n    \"o\": \"149.1425\",\n    \"t\": \"Nov 21, 2017 8:22:00 AM\"\n  },\n  {\n    \"c\": \"149.131\",\n    \"h\": \"149.1465\",\n    \"l\": \"149.126\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 8:23:00 AM\"\n  },\n  {\n    \"c\": \"149.1325\",\n    \"h\": \"149.1365\",\n    \"l\": \"149.1245\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 8:24:00 AM\"\n  },\n  {\n    \"c\": \"149.1565\",\n    \"h\": \"149.157\",\n    \"l\": \"149.1335\",\n    \"o\": \"149.1335\",\n    \"t\": \"Nov 21, 2017 8:25:00 AM\"\n  },\n  {\n    \"c\": \"149.208\",\n    \"h\": \"149.21\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1555\",\n    \"t\": \"Nov 21, 2017 8:26:00 AM\"\n  },\n  {\n    \"c\": \"149.198\",\n    \"h\": \"149.218\",\n    \"l\": \"149.1915\",\n    \"o\": \"149.207\",\n    \"t\": \"Nov 21, 2017 8:27:00 AM\"\n  },\n  {\n    \"c\": \"149.202\",\n    \"h\": \"149.207\",\n    \"l\": \"149.195\",\n    \"o\": \"149.196\",\n    \"t\": \"Nov 21, 2017 8:28:00 AM\"\n  },\n  {\n    \"c\": \"149.216\",\n    \"h\": \"149.2235\",\n    \"l\": \"149.191\",\n    \"o\": \"149.2035\",\n    \"t\": \"Nov 21, 2017 8:29:00 AM\"\n  },\n  {\n    \"c\": \"149.193\",\n    \"h\": \"149.216\",\n    \"l\": \"149.185\",\n    \"o\": \"149.2145\",\n    \"t\": \"Nov 21, 2017 8:30:00 AM\"\n  },\n  {\n    \"c\": \"149.1835\",\n    \"h\": \"149.197\",\n    \"l\": \"149.1835\",\n    \"o\": \"149.193\",\n    \"t\": \"Nov 21, 2017 8:31:00 AM\"\n  },\n  {\n    \"c\": \"149.1735\",\n    \"h\": \"149.1905\",\n    \"l\": \"149.1735\",\n    \"o\": \"149.182\",\n    \"t\": \"Nov 21, 2017 8:32:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1835\",\n    \"l\": \"149.1705\",\n    \"o\": \"149.174\",\n    \"t\": \"Nov 21, 2017 8:33:00 AM\"\n  },\n  {\n    \"c\": \"149.1795\",\n    \"h\": \"149.187\",\n    \"l\": \"149.1715\",\n    \"o\": \"149.1755\",\n    \"t\": \"Nov 21, 2017 8:34:00 AM\"\n  },\n  {\n    \"c\": \"149.2055\",\n    \"h\": \"149.209\",\n    \"l\": \"149.1805\",\n    \"o\": \"149.1805\",\n    \"t\": \"Nov 21, 2017 8:35:00 AM\"\n  },\n  {\n    \"c\": \"149.194\",\n    \"h\": \"149.2095\",\n    \"l\": \"149.1925\",\n    \"o\": \"149.2055\",\n    \"t\": \"Nov 21, 2017 8:36:00 AM\"\n  },\n  {\n    \"c\": \"149.1955\",\n    \"h\": \"149.2\",\n    \"l\": \"149.1845\",\n    \"o\": \"149.1935\",\n    \"t\": \"Nov 21, 2017 8:37:00 AM\"\n  },\n  {\n    \"c\": \"149.1995\",\n    \"h\": \"149.211\",\n    \"l\": \"149.184\",\n    \"o\": \"149.194\",\n    \"t\": \"Nov 21, 2017 8:38:00 AM\"\n  },\n  {\n    \"c\": \"149.202\",\n    \"h\": \"149.206\",\n    \"l\": \"149.1905\",\n    \"o\": \"149.199\",\n    \"t\": \"Nov 21, 2017 8:39:00 AM\"\n  },\n  {\n    \"c\": \"149.184\",\n    \"h\": \"149.2025\",\n    \"l\": \"149.17\",\n    \"o\": \"149.202\",\n    \"t\": \"Nov 21, 2017 8:40:00 AM\"\n  },\n  {\n    \"c\": \"149.187\",\n    \"h\": \"149.1945\",\n    \"l\": \"149.174\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 8:41:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1935\",\n    \"l\": \"149.1755\",\n    \"o\": \"149.1865\",\n    \"t\": \"Nov 21, 2017 8:42:00 AM\"\n  },\n  {\n    \"c\": \"149.146\",\n    \"h\": \"149.177\",\n    \"l\": \"149.146\",\n    \"o\": \"149.176\",\n    \"t\": \"Nov 21, 2017 8:43:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.1615\",\n    \"l\": \"149.1395\",\n    \"o\": \"149.1455\",\n    \"t\": \"Nov 21, 2017 8:44:00 AM\"\n  },\n  {\n    \"c\": \"149.1605\",\n    \"h\": \"149.162\",\n    \"l\": \"149.1405\",\n    \"o\": \"149.1445\",\n    \"t\": \"Nov 21, 2017 8:45:00 AM\"\n  },\n  {\n    \"c\": \"149.1515\",\n    \"h\": \"149.1605\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.1605\",\n    \"t\": \"Nov 21, 2017 8:46:00 AM\"\n  },\n  {\n    \"c\": \"149.1515\",\n    \"h\": \"149.152\",\n    \"l\": \"149.144\",\n    \"o\": \"149.151\",\n    \"t\": \"Nov 21, 2017 8:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.1735\",\n    \"l\": \"149.1495\",\n    \"o\": \"149.151\",\n    \"t\": \"Nov 21, 2017 8:48:00 AM\"\n  },\n  {\n    \"c\": \"149.1675\",\n    \"h\": \"149.177\",\n    \"l\": \"149.1565\",\n    \"o\": \"149.166\",\n    \"t\": \"Nov 21, 2017 8:49:00 AM\"\n  },\n  {\n    \"c\": \"149.175\",\n    \"h\": \"149.185\",\n    \"l\": \"149.1655\",\n    \"o\": \"149.1675\",\n    \"t\": \"Nov 21, 2017 8:50:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.1825\",\n    \"l\": \"149.159\",\n    \"o\": \"149.174\",\n    \"t\": \"Nov 21, 2017 8:51:00 AM\"\n  },\n  {\n    \"c\": \"149.184\",\n    \"h\": \"149.1845\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 8:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1815\",\n    \"h\": \"149.1845\",\n    \"l\": \"149.164\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 8:53:00 AM\"\n  },\n  {\n    \"c\": \"149.1575\",\n    \"h\": \"149.2005\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.182\",\n    \"t\": \"Nov 21, 2017 8:54:00 AM\"\n  },\n  {\n    \"c\": \"149.197\",\n    \"h\": \"149.198\",\n    \"l\": \"149.1585\",\n    \"o\": \"149.1585\",\n    \"t\": \"Nov 21, 2017 8:55:00 AM\"\n  },\n  {\n    \"c\": \"149.189\",\n    \"h\": \"149.198\",\n    \"l\": \"149.185\",\n    \"o\": \"149.1945\",\n    \"t\": \"Nov 21, 2017 8:56:00 AM\"\n  },\n  {\n    \"c\": \"149.18\",\n    \"h\": \"149.1895\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.1895\",\n    \"t\": \"Nov 21, 2017 8:57:00 AM\"\n  },\n  {\n    \"c\": \"149.158\",\n    \"h\": \"149.1785\",\n    \"l\": \"149.1505\",\n    \"o\": \"149.1785\",\n    \"t\": \"Nov 21, 2017 8:58:00 AM\"\n  },\n  {\n    \"c\": \"149.139\",\n    \"h\": \"149.1575\",\n    \"l\": \"149.128\",\n    \"o\": \"149.157\",\n    \"t\": \"Nov 21, 2017 8:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1095\",\n    \"h\": \"149.1385\",\n    \"l\": \"149.108\",\n    \"o\": \"149.1375\",\n    \"t\": \"Nov 21, 2017 9:00:00 AM\"\n  },\n  {\n    \"c\": \"149.1035\",\n    \"h\": \"149.1095\",\n    \"l\": \"149.098\",\n    \"o\": \"149.1095\",\n    \"t\": \"Nov 21, 2017 9:01:00 AM\"\n  },\n  {\n    \"c\": \"149.113\",\n    \"h\": \"149.113\",\n    \"l\": \"149.0845\",\n    \"o\": \"149.1035\",\n    \"t\": \"Nov 21, 2017 9:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.1225\",\n    \"l\": \"149.1075\",\n    \"o\": \"149.1125\",\n    \"t\": \"Nov 21, 2017 9:03:00 AM\"\n  },\n  {\n    \"c\": \"149.1225\",\n    \"h\": \"149.1375\",\n    \"l\": \"149.114\",\n    \"o\": \"149.1145\",\n    \"t\": \"Nov 21, 2017 9:04:00 AM\"\n  },\n  {\n    \"c\": \"149.134\",\n    \"h\": \"149.1365\",\n    \"l\": \"149.118\",\n    \"o\": \"149.1235\",\n    \"t\": \"Nov 21, 2017 9:05:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.0975\",\n    \"o\": \"149.1345\",\n    \"t\": \"Nov 21, 2017 9:06:00 AM\"\n  },\n  {\n    \"c\": \"149.104\",\n    \"h\": \"149.11\",\n    \"l\": \"149.1015\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 9:07:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.1045\",\n    \"l\": \"149.084\",\n    \"o\": \"149.1045\",\n    \"t\": \"Nov 21, 2017 9:08:00 AM\"\n  },\n  {\n    \"c\": \"149.092\",\n    \"h\": \"149.0985\",\n    \"l\": \"149.088\",\n    \"o\": \"149.093\",\n    \"t\": \"Nov 21, 2017 9:09:00 AM\"\n  },\n  {\n    \"c\": \"149.071\",\n    \"h\": \"149.0975\",\n    \"l\": \"149.0615\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 9:10:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.064\",\n    \"o\": \"149.0715\",\n    \"t\": \"Nov 21, 2017 9:11:00 AM\"\n  },\n  {\n    \"c\": \"149.0905\",\n    \"h\": \"149.098\",\n    \"l\": \"149.0655\",\n    \"o\": \"149.0905\",\n    \"t\": \"Nov 21, 2017 9:12:00 AM\"\n  },\n  {\n    \"c\": \"149.1175\",\n    \"h\": \"149.122\",\n    \"l\": \"149.0895\",\n    \"o\": \"149.0915\",\n    \"t\": \"Nov 21, 2017 9:13:00 AM\"\n  },\n  {\n    \"c\": \"149.133\",\n    \"h\": \"149.135\",\n    \"l\": \"149.1165\",\n    \"o\": \"149.1165\",\n    \"t\": \"Nov 21, 2017 9:14:00 AM\"\n  },\n  {\n    \"c\": \"149.0975\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.0975\",\n    \"o\": \"149.1325\",\n    \"t\": \"Nov 21, 2017 9:15:00 AM\"\n  },\n  {\n    \"c\": \"149.098\",\n    \"h\": \"149.111\",\n    \"l\": \"149.091\",\n    \"o\": \"149.097\",\n    \"t\": \"Nov 21, 2017 9:16:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.106\",\n    \"l\": \"149.078\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 9:17:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.081\",\n    \"o\": \"149.0905\",\n    \"t\": \"Nov 21, 2017 9:18:00 AM\"\n  },\n  {\n    \"c\": \"149.0885\",\n    \"h\": \"149.09\",\n    \"l\": \"149.081\",\n    \"o\": \"149.085\",\n    \"t\": \"Nov 21, 2017 9:19:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.091\",\n    \"l\": \"149.08\",\n    \"o\": \"149.0885\",\n    \"t\": \"Nov 21, 2017 9:20:00 AM\"\n  },\n  {\n    \"c\": \"149.094\",\n    \"h\": \"149.0995\",\n    \"l\": \"149.0755\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 9:21:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.0955\",\n    \"l\": \"149.0785\",\n    \"o\": \"149.0945\",\n    \"t\": \"Nov 21, 2017 9:22:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.092\",\n    \"l\": \"149.075\",\n    \"o\": \"149.08\",\n    \"t\": \"Nov 21, 2017 9:23:00 AM\"\n  },\n  {\n    \"c\": \"149.0825\",\n    \"h\": \"149.0935\",\n    \"l\": \"149.074\",\n    \"o\": \"149.0855\",\n    \"t\": \"Nov 21, 2017 9:24:00 AM\"\n  },\n  {\n    \"c\": \"149.0745\",\n    \"h\": \"149.082\",\n    \"l\": \"149.057\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 9:25:00 AM\"\n  },\n  {\n    \"c\": \"149.0395\",\n    \"h\": \"149.0745\",\n    \"l\": \"149.0395\",\n    \"o\": \"149.074\",\n    \"t\": \"Nov 21, 2017 9:26:00 AM\"\n  },\n  {\n    \"c\": \"149.0145\",\n    \"h\": \"149.041\",\n    \"l\": \"149.012\",\n    \"o\": \"149.04\",\n    \"t\": \"Nov 21, 2017 9:27:00 AM\"\n  },\n  {\n    \"c\": \"149.0085\",\n    \"h\": \"149.0235\",\n    \"l\": \"149.0065\",\n    \"o\": \"149.014\",\n    \"t\": \"Nov 21, 2017 9:28:00 AM\"\n  },\n  {\n    \"c\": \"149.0095\",\n    \"h\": \"149.0205\",\n    \"l\": \"149.005\",\n    \"o\": \"149.0095\",\n    \"t\": \"Nov 21, 2017 9:29:00 AM\"\n  },\n  {\n    \"c\": \"149.024\",\n    \"h\": \"149.05\",\n    \"l\": \"149.008\",\n    \"o\": \"149.008\",\n    \"t\": \"Nov 21, 2017 9:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0105\",\n    \"h\": \"149.0235\",\n    \"l\": \"148.9925\",\n    \"o\": \"149.0235\",\n    \"t\": \"Nov 21, 2017 9:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0435\",\n    \"h\": \"149.045\",\n    \"l\": \"149.01\",\n    \"o\": \"149.01\",\n    \"t\": \"Nov 21, 2017 9:32:00 AM\"\n  },\n  {\n    \"c\": \"149.042\",\n    \"h\": \"149.045\",\n    \"l\": \"149.0295\",\n    \"o\": \"149.045\",\n    \"t\": \"Nov 21, 2017 9:33:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.0515\",\n    \"l\": \"149.03\",\n    \"o\": \"149.0415\",\n    \"t\": \"Nov 21, 2017 9:34:00 AM\"\n  },\n  {\n    \"c\": \"149.05\",\n    \"h\": \"149.053\",\n    \"l\": \"149.038\",\n    \"o\": \"149.049\",\n    \"t\": \"Nov 21, 2017 9:35:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.056\",\n    \"l\": \"149.0465\",\n    \"o\": \"149.0505\",\n    \"t\": \"Nov 21, 2017 9:36:00 AM\"\n  },\n  {\n    \"c\": \"149.051\",\n    \"h\": \"149.054\",\n    \"l\": \"149.0415\",\n    \"o\": \"149.05\",\n    \"t\": \"Nov 21, 2017 9:37:00 AM\"\n  },\n  {\n    \"c\": \"149.0525\",\n    \"h\": \"149.071\",\n    \"l\": \"149.045\",\n    \"o\": \"149.051\",\n    \"t\": \"Nov 21, 2017 9:38:00 AM\"\n  },\n  {\n    \"c\": \"149.064\",\n    \"h\": \"149.066\",\n    \"l\": \"149.051\",\n    \"o\": \"149.0515\",\n    \"t\": \"Nov 21, 2017 9:39:00 AM\"\n  },\n  {\n    \"c\": \"149.066\",\n    \"h\": \"149.0695\",\n    \"l\": \"149.056\",\n    \"o\": \"149.065\",\n    \"t\": \"Nov 21, 2017 9:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0595\",\n    \"h\": \"149.0815\",\n    \"l\": \"149.0595\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 9:41:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0825\",\n    \"l\": \"149.059\",\n    \"o\": \"149.059\",\n    \"t\": \"Nov 21, 2017 9:42:00 AM\"\n  },\n  {\n    \"c\": \"149.1075\",\n    \"h\": \"149.11\",\n    \"l\": \"149.0805\",\n    \"o\": \"149.0815\",\n    \"t\": \"Nov 21, 2017 9:43:00 AM\"\n  },\n  {\n    \"c\": \"149.1035\",\n    \"h\": \"149.112\",\n    \"l\": \"149.0945\",\n    \"o\": \"149.108\",\n    \"t\": \"Nov 21, 2017 9:44:00 AM\"\n  },\n  {\n    \"c\": \"149.109\",\n    \"h\": \"149.1125\",\n    \"l\": \"149.0985\",\n    \"o\": \"149.103\",\n    \"t\": \"Nov 21, 2017 9:45:00 AM\"\n  },\n  {\n    \"c\": \"149.12\",\n    \"h\": \"149.121\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.1105\",\n    \"t\": \"Nov 21, 2017 9:46:00 AM\"\n  },\n  {\n    \"c\": \"149.1445\",\n    \"h\": \"149.1485\",\n    \"l\": \"149.1185\",\n    \"o\": \"149.12\",\n    \"t\": \"Nov 21, 2017 9:47:00 AM\"\n  },\n  {\n    \"c\": \"149.1455\",\n    \"h\": \"149.158\",\n    \"l\": \"149.1425\",\n    \"o\": \"149.1465\",\n    \"t\": \"Nov 21, 2017 9:48:00 AM\"\n  },\n  {\n    \"c\": \"149.147\",\n    \"h\": \"149.157\",\n    \"l\": \"149.138\",\n    \"o\": \"149.145\",\n    \"t\": \"Nov 21, 2017 9:49:00 AM\"\n  },\n  {\n    \"c\": \"149.1275\",\n    \"h\": \"149.152\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.147\",\n    \"t\": \"Nov 21, 2017 9:50:00 AM\"\n  },\n  {\n    \"c\": \"149.119\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.1155\",\n    \"o\": \"149.1275\",\n    \"t\": \"Nov 21, 2017 9:51:00 AM\"\n  },\n  {\n    \"c\": \"149.102\",\n    \"h\": \"149.1315\",\n    \"l\": \"149.101\",\n    \"o\": \"149.1175\",\n    \"t\": \"Nov 21, 2017 9:52:00 AM\"\n  },\n  {\n    \"c\": \"149.1175\",\n    \"h\": \"149.1175\",\n    \"l\": \"149.097\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 9:53:00 AM\"\n  },\n  {\n    \"c\": \"149.1145\",\n    \"h\": \"149.1175\",\n    \"l\": \"149.108\",\n    \"o\": \"149.117\",\n    \"t\": \"Nov 21, 2017 9:54:00 AM\"\n  },\n  {\n    \"c\": \"149.13\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1065\",\n    \"o\": \"149.1155\",\n    \"t\": \"Nov 21, 2017 9:55:00 AM\"\n  },\n  {\n    \"c\": \"149.1335\",\n    \"h\": \"149.134\",\n    \"l\": \"149.121\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 9:56:00 AM\"\n  },\n  {\n    \"c\": \"149.1305\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.128\",\n    \"o\": \"149.1345\",\n    \"t\": \"Nov 21, 2017 9:57:00 AM\"\n  },\n  {\n    \"c\": \"149.1275\",\n    \"h\": \"149.1325\",\n    \"l\": \"149.1275\",\n    \"o\": \"149.13\",\n    \"t\": \"Nov 21, 2017 9:58:00 AM\"\n  },\n  {\n    \"c\": \"149.1255\",\n    \"h\": \"149.1345\",\n    \"l\": \"149.1205\",\n    \"o\": \"149.128\",\n    \"t\": \"Nov 21, 2017 9:59:00 AM\"\n  },\n  {\n    \"c\": \"149.1285\",\n    \"h\": \"149.1285\",\n    \"l\": \"149.115\",\n    \"o\": \"149.124\",\n    \"t\": \"Nov 21, 2017 10:00:00 AM\"\n  },\n  {\n    \"c\": \"149.121\",\n    \"h\": \"149.13\",\n    \"l\": \"149.1205\",\n    \"o\": \"149.1285\",\n    \"t\": \"Nov 21, 2017 10:01:00 AM\"\n  },\n  {\n    \"c\": \"149.135\",\n    \"h\": \"149.136\",\n    \"l\": \"149.1195\",\n    \"o\": \"149.121\",\n    \"t\": \"Nov 21, 2017 10:02:00 AM\"\n  },\n  {\n    \"c\": \"149.1355\",\n    \"h\": \"149.1415\",\n    \"l\": \"149.1315\",\n    \"o\": \"149.135\",\n    \"t\": \"Nov 21, 2017 10:03:00 AM\"\n  },\n  {\n    \"c\": \"149.1435\",\n    \"h\": \"149.156\",\n    \"l\": \"149.136\",\n    \"o\": \"149.136\",\n    \"t\": \"Nov 21, 2017 10:04:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.17\",\n    \"l\": \"149.1365\",\n    \"o\": \"149.144\",\n    \"t\": \"Nov 21, 2017 10:05:00 AM\"\n  },\n  {\n    \"c\": \"149.2005\",\n    \"h\": \"149.2005\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1585\",\n    \"t\": \"Nov 21, 2017 10:06:00 AM\"\n  },\n  {\n    \"c\": \"149.187\",\n    \"h\": \"149.202\",\n    \"l\": \"149.1865\",\n    \"o\": \"149.2005\",\n    \"t\": \"Nov 21, 2017 10:07:00 AM\"\n  },\n  {\n    \"c\": \"149.163\",\n    \"h\": \"149.188\",\n    \"l\": \"149.1605\",\n    \"o\": \"149.188\",\n    \"t\": \"Nov 21, 2017 10:08:00 AM\"\n  },\n  {\n    \"c\": \"149.152\",\n    \"h\": \"149.175\",\n    \"l\": \"149.147\",\n    \"o\": \"149.1635\",\n    \"t\": \"Nov 21, 2017 10:09:00 AM\"\n  },\n  {\n    \"c\": \"149.1585\",\n    \"h\": \"149.163\",\n    \"l\": \"149.1445\",\n    \"o\": \"149.1515\",\n    \"t\": \"Nov 21, 2017 10:10:00 AM\"\n  },\n  {\n    \"c\": \"149.1665\",\n    \"h\": \"149.1715\",\n    \"l\": \"149.148\",\n    \"o\": \"149.158\",\n    \"t\": \"Nov 21, 2017 10:11:00 AM\"\n  },\n  {\n    \"c\": \"149.182\",\n    \"h\": \"149.1885\",\n    \"l\": \"149.1645\",\n    \"o\": \"149.1655\",\n    \"t\": \"Nov 21, 2017 10:12:00 AM\"\n  },\n  {\n    \"c\": \"149.1855\",\n    \"h\": \"149.187\",\n    \"l\": \"149.178\",\n    \"o\": \"149.1825\",\n    \"t\": \"Nov 21, 2017 10:13:00 AM\"\n  },\n  {\n    \"c\": \"149.1825\",\n    \"h\": \"149.1915\",\n    \"l\": \"149.18\",\n    \"o\": \"149.1855\",\n    \"t\": \"Nov 21, 2017 10:14:00 AM\"\n  },\n  {\n    \"c\": \"149.1685\",\n    \"h\": \"149.184\",\n    \"l\": \"149.1635\",\n    \"o\": \"149.1835\",\n    \"t\": \"Nov 21, 2017 10:15:00 AM\"\n  },\n  {\n    \"c\": \"149.1655\",\n    \"h\": \"149.174\",\n    \"l\": \"149.159\",\n    \"o\": \"149.167\",\n    \"t\": \"Nov 21, 2017 10:16:00 AM\"\n  },\n  {\n    \"c\": \"149.167\",\n    \"h\": \"149.176\",\n    \"l\": \"149.1645\",\n    \"o\": \"149.166\",\n    \"t\": \"Nov 21, 2017 10:17:00 AM\"\n  },\n  {\n    \"c\": \"149.1755\",\n    \"h\": \"149.1775\",\n    \"l\": \"149.1665\",\n    \"o\": \"149.167\",\n    \"t\": \"Nov 21, 2017 10:18:00 AM\"\n  },\n  {\n    \"c\": \"149.1895\",\n    \"h\": \"149.202\",\n    \"l\": \"149.1745\",\n    \"o\": \"149.176\",\n    \"t\": \"Nov 21, 2017 10:19:00 AM\"\n  },\n  {\n    \"c\": \"149.206\",\n    \"h\": \"149.208\",\n    \"l\": \"149.188\",\n    \"o\": \"149.1895\",\n    \"t\": \"Nov 21, 2017 10:20:00 AM\"\n  },\n  {\n    \"c\": \"149.198\",\n    \"h\": \"149.214\",\n    \"l\": \"149.1975\",\n    \"o\": \"149.2065\",\n    \"t\": \"Nov 21, 2017 10:21:00 AM\"\n  },\n  {\n    \"c\": \"149.1635\",\n    \"h\": \"149.1985\",\n    \"l\": \"149.1615\",\n    \"o\": \"149.1975\",\n    \"t\": \"Nov 21, 2017 10:22:00 AM\"\n  },\n  {\n    \"c\": \"149.1685\",\n    \"h\": \"149.1725\",\n    \"l\": \"149.1595\",\n    \"o\": \"149.1625\",\n    \"t\": \"Nov 21, 2017 10:23:00 AM\"\n  },\n  {\n    \"c\": \"149.1665\",\n    \"h\": \"149.174\",\n    \"l\": \"149.163\",\n    \"o\": \"149.168\",\n    \"t\": \"Nov 21, 2017 10:24:00 AM\"\n  },\n  {\n    \"c\": \"149.161\",\n    \"h\": \"149.1725\",\n    \"l\": \"149.155\",\n    \"o\": \"149.1665\",\n    \"t\": \"Nov 21, 2017 10:25:00 AM\"\n  },\n  {\n    \"c\": \"149.1495\",\n    \"h\": \"149.1655\",\n    \"l\": \"149.146\",\n    \"o\": \"149.1615\",\n    \"t\": \"Nov 21, 2017 10:26:00 AM\"\n  },\n  {\n    \"c\": \"149.139\",\n    \"h\": \"149.1645\",\n    \"l\": \"149.139\",\n    \"o\": \"149.1495\",\n    \"t\": \"Nov 21, 2017 10:27:00 AM\"\n  },\n  {\n    \"c\": \"149.099\",\n    \"h\": \"149.139\",\n    \"l\": \"149.088\",\n    \"o\": \"149.138\",\n    \"t\": \"Nov 21, 2017 10:28:00 AM\"\n  },\n  {\n    \"c\": \"149.09\",\n    \"h\": \"149.101\",\n    \"l\": \"149.089\",\n    \"o\": \"149.0995\",\n    \"t\": \"Nov 21, 2017 10:29:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.097\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.09\",\n    \"t\": \"Nov 21, 2017 10:30:00 AM\"\n  },\n  {\n    \"c\": \"149.0995\",\n    \"h\": \"149.1055\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.0775\",\n    \"t\": \"Nov 21, 2017 10:31:00 AM\"\n  },\n  {\n    \"c\": \"149.0865\",\n    \"h\": \"149.1035\",\n    \"l\": \"149.086\",\n    \"o\": \"149.0985\",\n    \"t\": \"Nov 21, 2017 10:32:00 AM\"\n  },\n  {\n    \"c\": \"149.0845\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0745\",\n    \"o\": \"149.0865\",\n    \"t\": \"Nov 21, 2017 10:33:00 AM\"\n  },\n  {\n    \"c\": \"149.048\",\n    \"h\": \"149.089\",\n    \"l\": \"149.048\",\n    \"o\": \"149.0845\",\n    \"t\": \"Nov 21, 2017 10:34:00 AM\"\n  },\n  {\n    \"c\": \"149.0495\",\n    \"h\": \"149.0685\",\n    \"l\": \"149.0365\",\n    \"o\": \"149.0485\",\n    \"t\": \"Nov 21, 2017 10:35:00 AM\"\n  },\n  {\n    \"c\": \"149.068\",\n    \"h\": \"149.068\",\n    \"l\": \"149.0425\",\n    \"o\": \"149.05\",\n    \"t\": \"Nov 21, 2017 10:36:00 AM\"\n  },\n  {\n    \"c\": \"149.0545\",\n    \"h\": \"149.0765\",\n    \"l\": \"149.0505\",\n    \"o\": \"149.0675\",\n    \"t\": \"Nov 21, 2017 10:37:00 AM\"\n  },\n  {\n    \"c\": \"149.081\",\n    \"h\": \"149.0835\",\n    \"l\": \"149.0535\",\n    \"o\": \"149.0535\",\n    \"t\": \"Nov 21, 2017 10:38:00 AM\"\n  },\n  {\n    \"c\": \"149.0715\",\n    \"h\": \"149.084\",\n    \"l\": \"149.0685\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 10:39:00 AM\"\n  },\n  {\n    \"c\": \"149.091\",\n    \"h\": \"149.091\",\n    \"l\": \"149.0695\",\n    \"o\": \"149.072\",\n    \"t\": \"Nov 21, 2017 10:40:00 AM\"\n  },\n  {\n    \"c\": \"149.0805\",\n    \"h\": \"149.0915\",\n    \"l\": \"149.0775\",\n    \"o\": \"149.091\",\n    \"t\": \"Nov 21, 2017 10:41:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.095\",\n    \"l\": \"149.077\",\n    \"o\": \"149.0805\",\n    \"t\": \"Nov 21, 2017 10:42:00 AM\"\n  },\n  {\n    \"c\": \"149.0835\",\n    \"h\": \"149.096\",\n    \"l\": \"149.0825\",\n    \"o\": \"149.096\",\n    \"t\": \"Nov 21, 2017 10:43:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.091\",\n    \"l\": \"149.077\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 10:44:00 AM\"\n  },\n  {\n    \"c\": \"149.082\",\n    \"h\": \"149.089\",\n    \"l\": \"149.076\",\n    \"o\": \"149.078\",\n    \"t\": \"Nov 21, 2017 10:45:00 AM\"\n  },\n  {\n    \"c\": \"149.101\",\n    \"h\": \"149.104\",\n    \"l\": \"149.083\",\n    \"o\": \"149.084\",\n    \"t\": \"Nov 21, 2017 10:46:00 AM\"\n  },\n  {\n    \"c\": \"149.085\",\n    \"h\": \"149.104\",\n    \"l\": \"149.083\",\n    \"o\": \"149.1\",\n    \"t\": \"Nov 21, 2017 10:47:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.092\",\n    \"l\": \"149.081\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:48:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.092\",\n    \"l\": \"149.08\",\n    \"o\": \"149.087\",\n    \"t\": \"Nov 21, 2017 10:49:00 AM\"\n  },\n  {\n    \"c\": \"149.079\",\n    \"h\": \"149.088\",\n    \"l\": \"149.077\",\n    \"o\": \"149.082\",\n    \"t\": \"Nov 21, 2017 10:50:00 AM\"\n  },\n  {\n    \"c\": \"149.103\",\n    \"h\": \"149.108\",\n    \"l\": \"149.077\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 10:51:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.111\",\n    \"l\": \"149.089\",\n    \"o\": \"149.102\",\n    \"t\": \"Nov 21, 2017 10:52:00 AM\"\n  },\n  {\n    \"c\": \"149.115\",\n    \"h\": \"149.115\",\n    \"l\": \"149.093\",\n    \"o\": \"149.094\",\n    \"t\": \"Nov 21, 2017 10:53:00 AM\"\n  },\n  {\n    \"c\": \"149.093\",\n    \"h\": \"149.117\",\n    \"l\": \"149.093\",\n    \"o\": \"149.114\",\n    \"t\": \"Nov 21, 2017 10:54:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.093\",\n    \"l\": \"149.08\",\n    \"o\": \"149.092\",\n    \"t\": \"Nov 21, 2017 10:55:00 AM\"\n  },\n  {\n    \"c\": \"149.073\",\n    \"h\": \"149.088\",\n    \"l\": \"149.064\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:56:00 AM\"\n  },\n  {\n    \"c\": \"149.086\",\n    \"h\": \"149.087\",\n    \"l\": \"149.072\",\n    \"o\": \"149.072\",\n    \"t\": \"Nov 21, 2017 10:57:00 AM\"\n  },\n  {\n    \"c\": \"149.087\",\n    \"h\": \"149.1\",\n    \"l\": \"149.082\",\n    \"o\": \"149.087\",\n    \"t\": \"Nov 21, 2017 10:58:00 AM\"\n  },\n  {\n    \"c\": \"149.084\",\n    \"h\": \"149.086\",\n    \"l\": \"149.075\",\n    \"o\": \"149.086\",\n    \"t\": \"Nov 21, 2017 10:59:00 AM\"\n  },\n  {\n    \"c\": \"149.074\",\n    \"h\": \"149.085\",\n    \"l\": \"149.07\",\n    \"o\": \"149.083\",\n    \"t\": \"Nov 21, 2017 11:00:00 AM\"\n  },\n  {\n    \"c\": \"149.082\",\n    \"h\": \"149.085\",\n    \"l\": \"149.073\",\n    \"o\": \"149.075\",\n    \"t\": \"Nov 21, 2017 11:01:00 AM\"\n  },\n  {\n    \"c\": \"149.095\",\n    \"h\": \"149.097\",\n    \"l\": \"149.081\",\n    \"o\": \"149.081\",\n    \"t\": \"Nov 21, 2017 11:02:00 AM\"\n  },\n  {\n    \"c\": \"149.08\",\n    \"h\": \"149.104\",\n    \"l\": \"149.08\",\n    \"o\": \"149.095\",\n    \"t\": \"Nov 21, 2017 11:03:00 AM\"\n  },\n  {\n    \"c\": \"149.081\",\n    \"h\": \"149.081\",\n    \"l\": \"149.079\",\n    \"o\": \"149.079\",\n    \"t\": \"Nov 21, 2017 11:04:00 AM\"\n  }\n]"
  },
  {
    "path": "app/src/main/java/com/tophold/example/MainActivity.java",
    "content": "package com.tophold.example;\n\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport com.tophold.example.base.BaseActivity;\nimport com.tophold.example.demo.fund.FundActivity;\nimport com.tophold.example.demo.kview.KViewActivity;\nimport com.tophold.example.demo.kview.beginner.ui.KViewHorizontalActivityActivity;\nimport com.tophold.example.demo.kview.beginner.ui.KViewVerticalActivity;\nimport com.tophold.example.demo.kview.btc.ui.HuobiListActivity;\nimport com.tophold.example.demo.kview.forex.ui.ForexListActivity;\nimport com.tophold.example.demo.pie.PieChartActivity;\nimport com.tophold.example.demo.seekbar.DoubleThumbSeekBarActivity;\nimport com.tophold.example.utils.RxUtils;\nimport com.tophold.trade.utils.StringUtils;\n\nimport java.util.concurrent.TimeUnit;\n\nimport io.reactivex.Observable;\nimport io.reactivex.ObservableEmitter;\nimport io.reactivex.ObservableOnSubscribe;\nimport io.reactivex.Scheduler;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport io.reactivex.schedulers.Schedulers;\n\npublic class MainActivity extends BaseActivity {\n    TextView mTextView;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        mTextView = (TextView) findViewById(R.id.version);\n        mTextView.setText(getVersionStr());\n    }\n\n    public String getVersionStr() {\n        String version = \"verisonName:\";\n        version += BuildConfig.VERSION_NAME;\n        version += \",versionCode(git head):\" + BuildConfig.VERSION_CODE;\n\n        return version;\n    }\n\n    public void fundView(View view) {\n        go(FundActivity.class);\n    }\n\n    public void kViewDemo(View view) {\n        go(KViewActivity.class);\n    }\n\n    public void onPieTest(View view) {\n        go(PieChartActivity.class);\n    }\n\n    public void onSeekBarTest(View view) {\n        go(DoubleThumbSeekBarActivity.class);\n    }\n\n\n    public void onRx(View view) {\n        Disposable disposable = Observable.create((ObservableOnSubscribe<String>) emitter -> {\n            while (true) {\n                emitter.onNext(\"a\");\n                Thread.sleep(500);\n                emitter.onNext(\"b\");\n                Thread.sleep(2000);\n                emitter.onNext(\"c\");\n                Thread.sleep(9000);\n                emitter.onNext(\"d\");\n            }\n        }).observeOn(Schedulers.io())\n                .compose(RxUtils.rxApiSchedulerHelper())\n                .sample(1000, TimeUnit.MILLISECONDS)\n                .subscribe(s -> Log.d(TAG, \"accept: \" + s));\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/MyApplication.java",
    "content": "package com.tophold.example;\n\nimport android.app.Application;\nimport android.content.Context;\n\nimport com.tophold.example.demo.kview.btc.api.HuobiWebSocket;\nimport com.tophold.example.demo.kview.forex.api.ForexWebSocket;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 21:38\n * 描 述 ：\n * ============================================================\n **/\npublic class MyApplication extends Application {\n    public static Context mAppContext;\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        mAppContext = this;\n        ForexWebSocket.getInstance().init();\n        HuobiWebSocket.getInstance().init();\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/tophold/example/base/BaseActivity.java",
    "content": "package com.tophold.example.base;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.graphics.drawable.Drawable;\nimport android.os.Bundle;\nimport android.support.annotation.ColorRes;\nimport android.support.annotation.DrawableRes;\nimport android.support.annotation.Nullable;\nimport android.support.v4.content.ContextCompat;\nimport android.support.v7.app.AppCompatActivity;\nimport android.util.Log;\nimport android.widget.Toast;\n\nimport org.greenrobot.eventbus.EventBus;\n\nimport io.reactivex.Observable;\nimport io.reactivex.Observer;\nimport io.reactivex.disposables.CompositeDisposable;\nimport io.reactivex.disposables.Disposable;\n\nimport com.tophold.example.demo.kview.forex.api.RetrofitManager;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf\n * 创建日期 ：2017/10/16 16:27\n * 描 述 ：\n * ============================================================\n **/\npublic class BaseActivity extends AppCompatActivity {\n    /**\n     * Activity 跳转\n     *\n     * @param clazz  目标activity\n     * @param bundle 传递参数\n     * @param finish 是否结束当前activity\n     */\n    public static final int NON_CODE = -1;\n\n    protected Context mContext = null;\n    protected String TAG = null;\n    protected Activity mActivity;\n    /**\n     * 对系统系统的toast进行简单封装，方便使用\n     */\n    private Toast toast = null;\n\n    private CompositeDisposable compositeDisposable;\n\n    @Override\n    public void setContentView(int view) {\n        super.setContentView(view);\n\n    }\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        mActivity = this;\n        mContext = this;\n        TAG = this.getClass().getSimpleName();\n        // getBundleExtras\n        Bundle extras = getIntent().getExtras();\n        if (null != extras) {\n            getBundleExtras(extras);\n        }\n        if (isBindEventBusHere()) {\n            EventBus.getDefault().register(mActivity);\n        }\n    }\n\n    public boolean isBindEventBusHere() {\n        return false;\n    }\n\n    protected void getBundleExtras(Bundle extras) {\n\n    }\n    protected Drawable getCompatDrawable(@DrawableRes int drawbaleId) {\n        return ContextCompat.getDrawable(mContext, drawbaleId);\n    }\n\n    protected int getCompatColor(@ColorRes int colorId) {\n        return ContextCompat.getColor(mContext, colorId);\n    }\n    /**\n     * 添加disposable\n     *\n     * @param disposable\n     */\n    public void unSubscription(Disposable disposable) {\n        if (compositeDisposable == null) {\n            synchronized (CompositeDisposable.class) {\n                if (compositeDisposable == null) {\n                    compositeDisposable = new CompositeDisposable();\n                }\n            }\n        }\n        compositeDisposable.add(disposable);\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        if (isBindEventBusHere()) {\n            EventBus.getDefault().unregister(mActivity);\n        }\n        if (compositeDisposable != null) {\n            Log.d(TAG, \"base activity dispose\");\n            compositeDisposable.clear();\n        }\n    }\n    /**\n     * @param observable\n     * @param observer\n     */\n    public void call(Observable observable, Observer observer) {\n       RetrofitManager.call(observable, observer);\n    }\n    /**\n     * startActivity\n     *\n     * @param clazz target Activity\n     */\n    public void go(Class<? extends Activity> clazz) {\n        _goActivity(clazz, null, NON_CODE, false);\n    }\n\n    /**\n     * startActivity with bundle\n     *\n     * @param clazz  target Activity\n     * @param bundle\n     */\n    public void go(Class<? extends Activity> clazz, Bundle bundle) {\n        _goActivity(clazz, bundle, NON_CODE, false);\n    }\n\n    /**\n     * startActivity then finish this\n     *\n     * @param clazz target Activity\n     */\n    public void goAndFinish(Class<? extends Activity> clazz) {\n        _goActivity(clazz, null, NON_CODE, true);\n    }\n\n    /**\n     * startActivity with bundle and then finish this\n     *\n     * @param clazz  target Activity\n     * @param bundle bundle extra\n     */\n    public void goAndFinish(Class<? extends Activity> clazz, Bundle bundle) {\n        _goActivity(clazz, bundle, NON_CODE, true);\n    }\n\n    /**\n     * startActivityForResult\n     *\n     * @param clazz\n     * @param requestCode\n     */\n    protected void goForResult(Class<? extends Activity> clazz, int requestCode) {\n        _goActivity(clazz, null, requestCode, false);\n    }\n\n    /**\n     * startActivityForResult with bundle\n     *\n     * @param clazz\n     * @param bundle\n     * @param requestCode\n     */\n    protected void goForResult(Class<? extends Activity> clazz, Bundle bundle, int requestCode) {\n        _goActivity(clazz, bundle, requestCode, false);\n    }\n\n    /**\n     * startActivityForResult then finish this\n     *\n     * @param clazz\n     * @param requestCode\n     */\n    protected void goForResultAndFinish(Class<? extends Activity> clazz, int requestCode) {\n        _goActivity(clazz, null, requestCode, true);\n    }\n\n    /**\n     * startActivityForResult with bundle and then finish this\n     *\n     * @param clazz\n     * @param bundle\n     * @param requestCode\n     */\n    protected void goForResultAndFinish(Class<? extends Activity> clazz, Bundle bundle, int requestCode) {\n        _goActivity(clazz, bundle, requestCode, true);\n    }\n\n\n    //可以立刻刷新Toast。推荐使用该方式。\n    public void showSingletonToast(String str) {\n        if (toast == null) {\n            toast = Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT);\n        } else {\n            toast.setText(str);\n        }\n        toast.show();\n    }\n\n    public void showToast(String msg) {\n        showToast(msg, Toast.LENGTH_SHORT);\n    }\n\n    public void showToast(String msg, int toastDuration) {\n        if (null != msg && (toastDuration == Toast.LENGTH_SHORT || toastDuration == Toast.LENGTH_LONG)) {\n            Toast.makeText(getApplicationContext(), msg, toastDuration).show();\n        }\n    }\n\n    private void _goActivity(Class<? extends Activity> clazz, Bundle bundle, int requestCode, boolean finish) {\n        if (null == clazz) {\n            throw new IllegalArgumentException(\"you must pass a target activity where to go.\");\n        }\n        Intent intent = new Intent(this, clazz);\n        if (null != bundle) {\n            intent.putExtras(bundle);\n        }\n        if (requestCode > NON_CODE) {\n            startActivityForResult(intent, requestCode);\n        } else {\n            startActivity(intent);\n        }\n        if (finish) {\n            finish();\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/base/BaseFragment.java",
    "content": "package com.tophold.example.base;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport org.greenrobot.eventbus.EventBus;\n\nimport io.reactivex.Observable;\nimport io.reactivex.Observer;\nimport io.reactivex.disposables.CompositeDisposable;\nimport io.reactivex.disposables.Disposable;\nimport com.tophold.example.demo.kview.forex.api.RetrofitManager;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 14:06\n * 描 述 ：\n * ============================================================\n **/\npublic class BaseFragment extends android.support.v4.app.Fragment {\n    CompositeDisposable disposables;\n\n    protected String TAG;\n    protected Context mContext;\n    protected Activity mActivity;\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        TAG = this.getClass().getSimpleName();\n        mContext = this.getActivity();\n        mActivity = getActivity();\n        if (isBindEventBusHere()) {\n            EventBus.getDefault().register(this);\n        }\n    }\n    public boolean isBindEventBusHere() {\n        return false;\n    }\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        if (isBindEventBusHere()) {\n            EventBus.getDefault().unregister(this);\n        }\n        if (disposables != null) disposables.clear();\n    }\n\n    public void unSubscription(Disposable disposable) {\n        if (disposables == null) {\n            synchronized (CompositeDisposable.class) {\n                if (disposables == null) {\n                    disposables = new CompositeDisposable();\n                }\n            }\n        }\n        disposables.add(disposable);\n    }\n    /**\n     * @param observable\n     * @param observer\n     */\n    public void call(Observable observable, Observer<?> observer) {\n        RetrofitManager.call(observable, observer);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/fund/FundActivity.java",
    "content": "package com.tophold.example.demo.fund;\n\nimport android.os.Bundle;\nimport android.util.Log;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport io.reactivex.Observable;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.schedulers.Schedulers;\nimport com.tophold.example.base.BaseActivity;\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.beginner.model.OriginFundMode;\nimport com.tophold.example.demo.kview.beginner.api.FundSimulateNetAPI;\nimport com.tophold.example.utils.GsonUtil;\nimport com.tophold.trade.utils.StringUtils;\nimport com.tophold.trade.view.fund.FundMode;\nimport com.tophold.trade.view.fund.FundView;\n\npublic class FundActivity extends BaseActivity {\n    private FundView mFundView;\n    List<OriginFundMode> mOriginFundModeList;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_fund);\n        initView();\n        initData();\n        loadData();\n\n    }\n\n    private void initView() {\n        mFundView = (FundView) findViewById(R.id.af_fv_fundview);\n\n        /**\n         * 定制,所有的画笔以及其它属性都已经暴露出来，有了更加大的定时灵活性。更多参数可以直接查看源码...\n         */\n        //常规set、get...\n        mFundView.getBrokenPaint().setColor(getResources().getColor(R.color.colorAccent));//设置折现颜色\n        mFundView.getInnerXPaint().setStrokeWidth(1);//设置内部x轴虚线的宽度,px\n        mFundView.getBrokenPaint().setStrokeWidth(1);\n        //链式调用\n        mFundView\n                .setBasePaddingTop(140)\n                .setBasePaddingLeft(50)\n                .setBasePaddingRight(40)\n                .setBasePaddingBottom(30)\n                .setLoadingText(\"正在加载，马上就来...\");\n\n    }\n\n    private void initData() {\n        mOriginFundModeList = new ArrayList<>();\n\n    }\n\n    private void loadData() {\n        Disposable subscribe = Observable.timer(StringUtils.getRadomNum(500, 3000), TimeUnit.MILLISECONDS)\n                .map(map -> {\n                    String originalFundData = FundSimulateNetAPI.getOriginalFundData(mContext);\n                    if (originalFundData == null) {\n                        Log.e(TAG, \"loadData: 从网络获取到的数据为空\");\n                        return null;\n                    }\n                    OriginFundMode[] originFunModes;\n                    try {\n                        originFunModes = GsonUtil.fromJson2Object(originalFundData, OriginFundMode[].class);\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                        return null;\n                    }\n                    List<OriginFundMode> OriginFundModeList = Arrays.asList(originFunModes);\n                    //开始适配图表数据\n                    return adapterData(OriginFundModeList);\n                })\n                .subscribeOn(Schedulers.computation())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(\n                        mData -> {\n                            if (StringUtils.isEmpty(mData)) {\n                                Log.d(TAG, \"loadData: data is empty!\");\n                                return;\n                            }\n                            mFundView.setDataList(mData);\n                        }\n                        , throwable -> throwable.printStackTrace());\n\n        unSubscription(subscribe);\n    }\n\n    private List<FundMode> adapterData(List<OriginFundMode> originFundModeList) {\n        List<FundMode> fundModeList = new ArrayList<>();//适配后的数据\n        for (OriginFundMode originFundMode : originFundModeList) {\n            FundMode fundMode = new FundMode(originFundMode.timestamp * 1000, originFundMode.actual);\n            fundModeList.add(fundMode);\n            Log.e(TAG, \"adapterData: 适配之前：\" + originFundMode.actual + \"----->>\" + fundMode.dataY);\n        }\n        return fundModeList;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/KViewActivity.kt",
    "content": "package com.tophold.example.demo.kview\n\nimport android.os.Bundle\nimport android.view.View\nimport com.tophold.example.BuildConfig\nimport com.tophold.example.R\nimport com.tophold.example.base.BaseActivity\nimport com.tophold.example.demo.kview.beginner.ui.KViewHorizontalActivityActivity\nimport com.tophold.example.demo.kview.beginner.ui.KViewVerticalActivity\nimport com.tophold.example.demo.kview.btc.ui.HuobiListActivity\nimport com.tophold.example.demo.kview.forex.ui.ForexListActivity\n\nclass KViewActivity : BaseActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_kview)\n    }\n\n    fun kViewVertical(view: View) {\n        go(KViewVerticalActivity::class.java)\n    }\n\n    fun kViewHorizontal(view: View) {\n        go(KViewHorizontalActivityActivity::class.java)\n    }\n\n    fun kViewEvaluation(view: View) {\n        go(ForexListActivity::class.java)\n    }\n\n    fun btnDemo(view: View) {\n        go(HuobiListActivity::class.java)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/beginner/api/FundSimulateNetAPI.java",
    "content": "package com.tophold.example.demo.kview.beginner.api;\n\nimport android.content.Context;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Scanner;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/10/25 15:43\n * 描 述 ：\n * ============================================================\n **/\npublic class FundSimulateNetAPI {\n    /**\n     * 获取去最原始的数据信息\n     *\n     * @return json data\n     */\n    public static String getOriginalFundData(Context context) {\n        InputStream input = null;\n        try {\n            input = context.getAssets().open(\"fund.json\");\n            String json = convertStreamToString(input);\n            return json;\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return null;\n    }\n\n    /**\n     * input 流转换为字符串\n     *\n     * @param is\n     * @return\n     */\n    private static String convertStreamToString(java.io.InputStream is) {\n        String s = null;\n        try {\n            Scanner scanner = new Scanner(is, \"UTF-8\").useDelimiter(\"\\\\A\");\n            if (scanner.hasNext()) s = scanner.next();\n            is.close();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        return s;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/beginner/api/KViewSimulateNetAPI.java",
    "content": "package com.tophold.example.demo.kview.beginner.api;\n\nimport android.content.Context;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Scanner;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/10/25 15:43\n * 描 述 ：\n * ============================================================\n **/\npublic class KViewSimulateNetAPI {\n    /**\n     * 获取去最原始的数据信息\n     *\n     * @return json data\n     */\n    public static String getOriginalFundData(Context context, int index) {\n        InputStream input = null;\n        try {\n            input = context.getAssets().open(\"timesharing\" + index + \".json\");\n            String json = convertStreamToString(input);\n            return json;\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return null;\n    }\n\n    /**\n     * input 流转换为字符串\n     *\n     * @param is\n     * @return\n     */\n    private static String convertStreamToString(InputStream is) {\n        String s = null;\n        try {\n            Scanner scanner = new Scanner(is, \"UTF-8\").useDelimiter(\"\\\\A\");\n            if (scanner.hasNext()) s = scanner.next();\n            is.close();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        return s;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/beginner/model/OriginFundMode.java",
    "content": "package com.tophold.example.demo.kview.beginner.model;\n\nimport java.io.Serializable;\n\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/10/24 15:00\n * 描 述 ：\n * ============================================================\n **/\npublic class OriginFundMode implements Serializable {\n    /**\n     * actual : 103\n     * createTime : Apr 10, 2017 12:04:14 AM\n     * economicId : 518\n     * forecast : 102\n     * historyId : 449366\n     * previous : 103\n     * revised :\n     * timestamp : 1456213500\n     */\n\n    public String actual;\n    public String createTime;\n    public int economicId;\n    public String forecast;\n    public int historyId;\n    public String previous;\n    public String revised;\n    public long timestamp;\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/beginner/model/OriginQuotes.java",
    "content": "package com.tophold.example.demo.kview.beginner.model;\n\nimport java.io.Serializable;\n\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/11/21 11:09\n * 描 述 ：原始数据\n * ============================================================\n **/\npublic class OriginQuotes implements Serializable {\n    /**\n     * t : 2016-10-25 12:06:00\n     * o : 2357.25\n     * h : 2357.25\n     * l : 2357.25\n     * c : 2357.25\n     */\n    public String t;\n    public String o;\n    public String h;\n    public String l;\n    public String c;\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/beginner/ui/KViewHorizontalActivityActivity.java",
    "content": "package com.tophold.example.demo.kview.beginner.ui;\n\nimport android.os.Bundle;\nimport android.support.annotation.ColorRes;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.Button;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.google.gson.reflect.TypeToken;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport io.reactivex.Observable;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.schedulers.Schedulers;\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.beginner.model.OriginQuotes;\nimport com.tophold.example.demo.kview.beginner.api.KViewSimulateNetAPI;\nimport com.tophold.example.base.BaseActivity;\nimport com.tophold.trade.utils.FormatUtil;\nimport com.tophold.example.utils.GsonUtil;\nimport com.tophold.trade.utils.StringUtils;\nimport com.tophold.trade.utils.TimeUtils;\nimport com.tophold.trade.view.kview.KView;\nimport com.tophold.trade.view.kview.KViewListener;\nimport com.tophold.trade.view.kview.Quotes;\n\n/**\n * timesharing0:模拟的是加载更多的数据，注意，会分段取，模拟的是多次加载更多\n * timesharing1：模拟的是api请求的数据集合，注意：一次加载完毕，模拟的是第一次加载的数据\n * timesharing2：模拟的是实时**推送**的数据，注意：会分段取，一次取一个。\n */\npublic class KViewHorizontalActivityActivity extends BaseActivity {\n    //bind view\n    private LinearLayout mAkvLlContainer;\n    private TextView mAkvTvH;\n    private TextView mAkvTvO;\n    private TextView mAkvTvTime;\n    private TextView mAkvTvL;\n    private TextView mAkvTvC;\n    private TextView mAkvTvP;\n    private KView mAkvKvKview;\n\n    //模拟网络过来的列表数据\n    List<Quotes> mQuotesList;\n    //模拟加载更多的数据\n    List<Quotes> mLoadMoreData;\n    //模拟socket推送过来的单个数据\n    List<Quotes> mPushData;\n    //加载更多，加载到哪儿了。因为真实应用中，也存在加载完毕的情况。这里对应加载到list的最后\n    int index = 0;\n\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_kview_horizontal);\n        initView();\n        initData();\n        loadData();\n        pushData();\n    }\n\n    private void pushData() {\n        Disposable disposable = Observable.interval(StringUtils.getRadomNum(300, 3000), TimeUnit.MILLISECONDS)\n                .subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(\n                        data -> {\n                            int size = mPushData.size();\n                            if (data < size) {\n                                mAkvKvKview.pushKViewData(mPushData.get(data.intValue()), 0);\n                            } else {\n\n                            }\n\n\n                        }\n                        , throwable -> throwable.printStackTrace());\n\n        unSubscription(disposable);\n    }\n\n    private void initView() {\n        mAkvLlContainer = (LinearLayout) findViewById(R.id.akv_ll_container);\n        mAkvTvH = (TextView) findViewById(R.id.akv_tv_h);\n        mAkvTvO = (TextView) findViewById(R.id.akv_tv_o);\n        mAkvTvTime = (TextView) findViewById(R.id.akv_tv_time);\n        mAkvTvL = (TextView) findViewById(R.id.akv_tv_l);\n        mAkvTvC = (TextView) findViewById(R.id.akv_tv_c);\n        mAkvTvP = (TextView) findViewById(R.id.akv_tv_p);\n        mAkvKvKview = (KView) findViewById(R.id.akv_kv_kview);\n    }\n\n    private void initData() {\n        mQuotesList = new ArrayList<>();\n        mLoadMoreData = new ArrayList<>();\n        mPushData = new ArrayList<>();\n\n        //这里先预加载加载更多的数据，然后加载更多的时候分段取出来，模拟加载更多\n        initLoadMoreData();\n\n        //pushData\n        initPushData();\n\n    }\n\n    private void initPushData() {\n        String originalFundData = KViewSimulateNetAPI.getOriginalFundData(mContext, 2);\n        if (originalFundData == null) {\n            Log.e(TAG, \"loadData: 从网络获取到的数据为空\");\n            return;\n        }\n        List<OriginQuotes> OriginFundModeList;\n        try {\n            OriginFundModeList = GsonUtil.fromJson2Object(originalFundData, new TypeToken<List<OriginQuotes>>() {\n            }.getType());\n        } catch (Exception e) {\n            e.printStackTrace();\n            return;\n        }\n        //开始适配图表数据\n        mPushData = adapterData(OriginFundModeList);\n\n    }\n\n    private void initLoadMoreData() {\n        String originalFundData = KViewSimulateNetAPI.getOriginalFundData(mContext, 0);\n        if (originalFundData == null) {\n            Log.e(TAG, \"loadData: 从网络获取到的数据为空\");\n            return;\n        }\n        try {\n            List<OriginQuotes> quotesList = GsonUtil.fromJson2Object(originalFundData,\n                    new TypeToken<List<OriginQuotes>>() {\n                    }.getType());\n            mLoadMoreData = adapterData(quotesList);\n        } catch (Exception e) {\n            e.printStackTrace();\n            return;\n        }\n    }\n\n    private void loadData() {\n        //模拟网络环境加载数据列表\n        Disposable disposable = Observable.timer(StringUtils.getRadomNum(500, 2000),\n                TimeUnit.MILLISECONDS)\n                .doOnNext(data -> {\n                    String originalData = KViewSimulateNetAPI.getOriginalFundData(mContext, 2);\n                    if (originalData == null) {\n                        Log.e(TAG, \"loadData: 从网络获取到的数据为空\");\n                        return;\n                    }\n                    try {\n                        List<OriginQuotes> originQuotes = GsonUtil\n                                .fromJson2Object(originalData, new TypeToken<List<OriginQuotes>>() {\n                                }.getType());\n                        mQuotesList = adapterData(originQuotes);\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                        Log.e(TAG, \"loadData: json转换错误\");\n                        return;\n                    }\n                })\n                .subscribeOn(Schedulers.computation())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(\n                        data -> mAkvKvKview.setKViewData(mQuotesList, new KViewListener.MasterTouchListener() {\n                            @Override\n                            public void onLongTouch(Quotes preQuotes, Quotes currentQuotes) {\n                                showContanier(preQuotes, currentQuotes);\n                            }\n\n                            @Override\n                            public void onUnLongTouch() {\n                                mAkvLlContainer.setVisibility(View.INVISIBLE);\n                            }\n\n                            @Override\n                            public void needLoadMore() {\n                                loadMore();\n                            }\n                        }),\n                        Throwable::printStackTrace\n                );\n        unSubscription(disposable);\n    }\n\n    private void loadMore() {\n        if (mLoadMoreData == null) return;\n        Disposable disposable = Observable.timer(StringUtils.getRadomNum(1000, 5000), TimeUnit.MILLISECONDS)\n                .subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(\n                        data -> {\n                            int size = mLoadMoreData.size();\n                            int min = size / 20;\n                            int max = size / 5;//一次最多加载多少\n                            int loadSize = StringUtils.getRadomNum(min, max);\n                            if (index == loadSize) {\n                                //没有更多数据了\n                                mAkvKvKview.loadMoreNoData();\n                            }\n                            if ((index + loadSize) > mLoadMoreData.size()) {\n                                loadSize = mLoadMoreData.size();\n                            }\n                            List<Quotes> loadList = mLoadMoreData.subList(index, index + loadSize);\n                            index = index + loadSize;//重置起始位置\n                            mAkvKvKview.loadKViewData(loadList);\n                        }\n                        , throwable -> throwable.printStackTrace());\n        unSubscription(disposable);\n\n    }\n\n    private List<Quotes> adapterData(List<OriginQuotes> originFundModeList) {\n        List<Quotes> fundModeList = new ArrayList<>();//适配后的数据\n        for (OriginQuotes OriginQuotes : originFundModeList) {\n            Quotes Quotes = new Quotes(OriginQuotes.o, OriginQuotes.h, OriginQuotes.l,\n                    OriginQuotes.c, OriginQuotes.t);\n            fundModeList.add(Quotes);\n        }\n        return fundModeList;\n    }\n\n    private void showContanier(Quotes preQuotes, Quotes currentQuotes) {\n        mAkvLlContainer.setVisibility(View.VISIBLE);\n        int digits = 4;\n        boolean isPositive;\n        String precent;\n        double dis = (currentQuotes.c - preQuotes.c) / currentQuotes.c * 100;\n        isPositive = dis >= 0;\n        precent = FormatUtil.formatBySubString(dis, 2);\n        precent += \"%\";\n\n        //\n        mAkvTvH.setText(FormatUtil.numFormat(currentQuotes.h, digits));\n        mAkvTvO.setText(FormatUtil.numFormat(currentQuotes.o, digits));\n        mAkvTvL.setText(FormatUtil.numFormat(currentQuotes.l, digits));\n        mAkvTvC.setText(FormatUtil.numFormat(currentQuotes.c, digits));\n        mAkvTvP.setText(precent);\n        mAkvTvTime.setText(TimeUtils.millis2String(currentQuotes.t, new SimpleDateFormat(\"MM-dd HH:mm\")));\n\n        if (isPositive) {\n            mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n        } else {\n            mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n        }\n    }\n\n    private int getMyColor(@ColorRes int colorId) {\n        return getResources().getColor(colorId);\n    }\n\n    public void showCandle(View view) {\n        boolean showTimSharing = mAkvKvKview.isShowTimSharing();\n        mAkvKvKview.setShowTimSharing(!showTimSharing);\n        if (!showTimSharing) {\n            ((Button) view).setText(\"点击展示蜡烛图\");\n        } else {\n            ((Button) view).setText(\"点击展示分时图\");\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/beginner/ui/KViewVerticalActivity.java",
    "content": "package com.tophold.example.demo.kview.beginner.ui;\n\nimport android.os.Bundle;\nimport android.support.annotation.ColorRes;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.Button;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.google.gson.reflect.TypeToken;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport io.reactivex.Observable;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.schedulers.Schedulers;\nimport com.tophold.example.base.BaseActivity;\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.beginner.api.KViewSimulateNetAPI;\nimport com.tophold.example.demo.kview.beginner.model.OriginQuotes;\nimport com.tophold.trade.utils.FormatUtil;\nimport com.tophold.example.utils.GsonUtil;\nimport com.tophold.trade.utils.StringUtils;\nimport com.tophold.trade.utils.TimeUtils;\nimport com.tophold.trade.view.kview.KView;\nimport com.tophold.trade.view.kview.KViewListener;\nimport com.tophold.trade.view.kview.Quotes;\n\n/**\n * timesharing0:模拟的是加载更多的数据，注意，会分段取，模拟的是多次加载更多\n * timesharing1：模拟的是api请求的数据集合，注意：一次加载完毕，模拟的是第一次加载的数据\n * timesharing2：模拟的是实时**推送**的数据，注意：会分段取，一次取一个。\n */\npublic class KViewVerticalActivity extends BaseActivity {\n    //bind view\n    private LinearLayout mAkvLlContainer;\n    private TextView mAkvTvH;\n    private TextView mAkvTvO;\n    private TextView mAkvTvTime;\n    private TextView mAkvTvL;\n    private TextView mAkvTvC;\n    private TextView mAkvTvP;\n    private KView mAkvKvKview;\n    private Button mAkvBtnShowCandle;\n    private Button mAkvBtnShowMinnor;\n\n    //模拟网络过来的列表数据\n    List<Quotes> mQuotesList;\n    //模拟加载更多的数据\n    List<Quotes> mLoadMoreData;\n    //模拟socket推送过来的单个数据\n    List<Quotes> mPushData;\n    //加载更多，加载到哪儿了。因为真实应用中，也存在加载完毕的情况。这里对应加载到list的最后\n    int index = 0;\n\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_kview_vertical);\n        initView();\n        initData();\n        loadData();\n        pushData();\n    }\n\n    private void pushData() {\n        Disposable disposable = Observable.interval(StringUtils.getRadomNum(300, 3000), TimeUnit.MILLISECONDS)\n                .subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(\n                        data -> {\n                            int size = mPushData.size();\n                            if (data < size) {\n                                mAkvKvKview.pushKViewData(mPushData.get(data.intValue()), 0);\n                            } else {\n\n                            }\n\n\n                        }\n                        , throwable -> throwable.printStackTrace());\n\n        unSubscription(disposable);\n    }\n\n    private void initView() {\n        mAkvLlContainer = (LinearLayout) findViewById(R.id.akv_ll_container);\n        mAkvTvH = (TextView) findViewById(R.id.akv_tv_h);\n        mAkvTvO = (TextView) findViewById(R.id.akv_tv_o);\n        mAkvTvTime = (TextView) findViewById(R.id.akv_tv_time);\n        mAkvTvL = (TextView) findViewById(R.id.akv_tv_l);\n        mAkvTvC = (TextView) findViewById(R.id.akv_tv_c);\n        mAkvTvP = (TextView) findViewById(R.id.akv_tv_p);\n        mAkvKvKview = (KView) findViewById(R.id.akv_kv_kview);\n        mAkvBtnShowCandle = (Button) findViewById(R.id.akv_btn_showCandle);\n        mAkvBtnShowMinnor = (Button) findViewById(R.id.akv_btn_showMinnor);\n    }\n\n    private void initData() {\n        mQuotesList = new ArrayList<>();\n        mLoadMoreData = new ArrayList<>();\n        mPushData = new ArrayList<>();\n\n        //这里先预加载加载更多的数据，然后加载更多的时候分段取出来，模拟加载更多\n        initLoadMoreData();\n\n        //pushData\n        initPushData();\n\n    }\n\n    private void initPushData() {\n        String originalFundData = KViewSimulateNetAPI.getOriginalFundData(mContext, 3);\n        if (originalFundData == null) {\n            Log.e(TAG, \"loadData: 从网络获取到的数据为空\");\n            return;\n        }\n        List<OriginQuotes> OriginFundModeList;\n        try {\n            OriginFundModeList = GsonUtil.fromJson2Object(originalFundData, new TypeToken<List<OriginQuotes>>() {\n            }.getType());\n        } catch (Exception e) {\n            e.printStackTrace();\n            return;\n        }\n        //开始适配图表数据\n        mPushData = adapterData(OriginFundModeList);\n\n    }\n\n    private void initLoadMoreData() {\n        String originalFundData = KViewSimulateNetAPI.getOriginalFundData(mContext, 3);\n        if (originalFundData == null) {\n            Log.e(TAG, \"loadData: 从网络获取到的数据为空\");\n            return;\n        }\n        try {\n            List<OriginQuotes> quotesList = GsonUtil.fromJson2Object(originalFundData,\n                    new TypeToken<List<OriginQuotes>>() {\n                    }.getType());\n            mLoadMoreData = adapterData(quotesList);\n        } catch (Exception e) {\n            e.printStackTrace();\n            return;\n        }\n    }\n\n    private void loadData() {\n        //模拟网络环境加载数据列表\n        Disposable disposable = Observable.timer(StringUtils.getRadomNum(500, 2000),\n                TimeUnit.MILLISECONDS)\n                .doOnNext(data -> {\n                    String originalData = KViewSimulateNetAPI.getOriginalFundData(mContext, 3);\n                    if (originalData == null) {\n                        Log.e(TAG, \"loadData: 从网络获取到的数据为空\");\n                        return;\n                    }\n                    try {\n                        List<OriginQuotes> originQuotes = GsonUtil\n                                .fromJson2Object(originalData, new TypeToken<List<OriginQuotes>>() {\n                                }.getType());\n                        mQuotesList = adapterData(originQuotes);\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                        Log.e(TAG, \"loadData: json转换错误\");\n                        return;\n                    }\n                })\n                .subscribeOn(Schedulers.computation())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(\n                        data -> {\n                            mAkvKvKview.setKViewData(mQuotesList, new KViewListener.MasterTouchListener() {\n                                @Override\n                                public void onLongTouch(Quotes preQuotes, Quotes currentQuotes) {\n                                    showContanier(preQuotes, currentQuotes);\n                                }\n\n                                @Override\n                                public void onUnLongTouch() {\n                                    mAkvLlContainer.setVisibility(View.INVISIBLE);\n                                }\n\n                                @Override\n                                public void needLoadMore() {\n                                    loadMore();\n                                }\n                            });\n                        },\n                        throwable -> throwable.printStackTrace()\n                );\n        unSubscription(disposable);\n    }\n\n    private void loadMore() {\n        if (mLoadMoreData == null) return;\n        Disposable disposable = Observable.timer(StringUtils.getRadomNum(1000, 5000), TimeUnit.MILLISECONDS)\n                .subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(\n                        data -> {\n                            int size = mLoadMoreData.size();\n                            int min = size / 20;\n                            int max = size / 5;//一次最多加载多少\n                            int loadSize = StringUtils.getRadomNum(min, max);\n                            if (index == loadSize) {\n                                //没有更多数据了\n                                mAkvKvKview.loadMoreNoData();\n                            }\n                            if ((index + loadSize) > mLoadMoreData.size()) {\n                                loadSize = mLoadMoreData.size();\n                            }\n                            List<Quotes> loadList = mLoadMoreData.subList(index, index + loadSize);\n                            index = index + loadSize;//重置起始位置\n                            mAkvKvKview.loadKViewData(loadList);\n                        }\n                        , throwable -> throwable.printStackTrace());\n        unSubscription(disposable);\n\n    }\n\n    public void showCandle(View view) {\n        boolean showTimSharing = mAkvKvKview.isShowTimSharing();\n        mAkvKvKview.setShowTimSharing(!showTimSharing);\n        if (!showTimSharing) {\n            mAkvBtnShowCandle.setText(\"点击展示蜡烛图\");\n        } else {\n            mAkvBtnShowCandle.setText(\"点击展示分时图\");\n        }\n    }\n\n    public void showMinor(View view) {\n        boolean showMinor = mAkvKvKview.isShowMinor();\n        mAkvKvKview.setShowMinor(!showMinor);\n        if (!showMinor) {\n            mAkvBtnShowMinnor.setText(\"点击不显示副图\");\n        } else {\n            mAkvBtnShowMinnor.setText(\"点击显示副图\");\n        }\n    }\n\n    private List<Quotes> adapterData(List<OriginQuotes> originFundModeList) {\n        List<Quotes> fundModeList = new ArrayList<>();//适配后的数据\n        for (OriginQuotes OriginQuotes : originFundModeList) {\n            Quotes Quotes = new Quotes(OriginQuotes.o, OriginQuotes.h, OriginQuotes.l,\n                    OriginQuotes.c, OriginQuotes.t);\n            fundModeList.add(Quotes);\n        }\n        return fundModeList;\n    }\n\n    private void showContanier(Quotes preQuotes, Quotes currentQuotes) {\n        mAkvLlContainer.setVisibility(View.VISIBLE);\n        int digits = 4;\n        boolean isPositive;\n        String precent;\n        double dis = (currentQuotes.c - preQuotes.c) / currentQuotes.c * 100;\n        isPositive = dis >= 0;\n        precent = FormatUtil.formatBySubString(dis, 2);\n        precent += \"%\";\n\n        //\n        mAkvTvH.setText(FormatUtil.numFormat(currentQuotes.h, digits));\n        mAkvTvO.setText(FormatUtil.numFormat(currentQuotes.o, digits));\n        mAkvTvL.setText(FormatUtil.numFormat(currentQuotes.l, digits));\n        mAkvTvC.setText(FormatUtil.numFormat(currentQuotes.c, digits));\n        mAkvTvP.setText(precent);\n        mAkvTvTime.setText(TimeUtils.millis2String(currentQuotes.t, new SimpleDateFormat(\"MM-dd HH:mm\")));\n\n        if (isPositive) {\n            mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n        } else {\n            mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n        }\n    }\n\n    private int getMyColor(@ColorRes int colorId) {\n        return getResources().getColor(colorId);\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/api/GZipUtil.java",
    "content": "package com.tophold.example.demo.kview.btc.api;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.zip.GZIPInputStream;\nimport java.util.zip.GZIPOutputStream;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipFile;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/28 14:14\n * 描 述 ：\n * ============================================================\n **/\npublic class GZipUtil {\n    // 压缩\n    public static byte[] compress(byte[] data) throws IOException {\n        if (data == null || data.length == 0) {\n            return null;\n        }\n        ByteArrayOutputStream out = new ByteArrayOutputStream();\n        GZIPOutputStream gzip = new GZIPOutputStream(out);\n        gzip.write(data);\n        gzip.close();\n        return out.toByteArray();//out.toString(\"ISO-8859-1\");\n    }\n\n    public static byte[] compress(String str) throws IOException {\n        if (str == null || str.length() == 0) {\n            return null;\n        }\n        return compress(str.getBytes(\"utf-8\"));\n    }\n\n    // 解压缩\n    public static byte[] uncompress(byte[] data) throws IOException {\n        if (data == null || data.length == 0) {\n            return data;\n        }\n        ByteArrayOutputStream out = new ByteArrayOutputStream();\n        ByteArrayInputStream in = new ByteArrayInputStream(data);\n        GZIPInputStream gunzip = new GZIPInputStream(in);\n        byte[] buffer = new byte[256];\n        int n;\n        while ((n = gunzip.read(buffer)) >= 0) {\n            out.write(buffer, 0, n);\n        }\n        gunzip.close();\n        in.close();\n        return out.toByteArray();\n    }\n\n    public static String uncompressBytes(byte[] data) throws IOException {\n        byte[] bytes = uncompress(data);\n        return new String(bytes);\n    }\n\n    public static String uncompress(String str) throws IOException {\n        if (str == null || str.length() == 0) {\n            return str;\n        }\n        byte[] data = uncompress(str.getBytes(\"utf-8\")); // ISO-8859-1\n        return new String(data);\n    }\n\n    /**\n     * @param @param  unZipfile\n     * @param @param  destFile 指定读取文件，需要从压缩文件中读取文件内容的文件名\n     * @param @return 设定文件\n     * @return String 返回类型\n     * @throws\n     * @Title: unZip\n     * @Description: TODO(这里用一句话描述这个方法的作用)\n     */\n    public static String unZip(String unZipfile, String destFile) {// unZipfileName需要解压的zip文件名\n        InputStream inputStream;\n        String inData = null;\n        try {\n            // 生成一个zip的文件\n            File f = new File(unZipfile);\n            ZipFile zipFile = new ZipFile(f);\n\n            // 遍历zipFile中所有的实体，并把他们解压出来\n            ZipEntry entry = zipFile.getEntry(destFile);\n            if (!entry.isDirectory()) {\n                // 获取出该压缩实体的输入流\n                inputStream = zipFile.getInputStream(entry);\n\n                ByteArrayOutputStream out = new ByteArrayOutputStream();\n                byte[] bys = new byte[4096];\n                for (int p = -1; (p = inputStream.read(bys)) != -1; ) {\n                    out.write(bys, 0, p);\n                }\n                inData = out.toString();\n                out.close();\n                inputStream.close();\n            }\n            zipFile.close();\n        } catch (IOException ioe) {\n            ioe.printStackTrace();\n        }\n        return inData;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/api/HttpCommonInterceptor.java",
    "content": "package com.tophold.example.demo.kview.btc.api;\n\nimport android.util.Log;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport okhttp3.Interceptor;\nimport okhttp3.Request;\nimport okhttp3.Response;\n\n/**\n * 拦截器\n *\n * 向请求头里添加公共参数\n * Created by zhouwei on 16/11/10.\n */\n\npublic class HttpCommonInterceptor implements Interceptor {\n\n    private Map<String,String> mHeaderParamsMap = new HashMap<>();\n    public HttpCommonInterceptor() {\n\n    }\n\n    @Override\n    public Response intercept(Chain chain) throws IOException {\n        Log.d(\"HttpCommonInterceptor\",\"add common params\");\n        Request oldRequest = chain.request();\n\n        // 添加新的参数，添加到url 中\n       /* HttpUrl.Builder authorizedUrlBuilder = oldRequest.url()\n                .newBuilder()\n                .scheme(oldRequest.url().scheme())\n                .host(oldRequest.url().host());*/\n\n        // 新的请求\n\n        Request.Builder requestBuilder =  oldRequest.newBuilder();\n                requestBuilder.method(oldRequest.method(), oldRequest.body());\n        //添加公共参数,添加到header中\n        if(mHeaderParamsMap.size() > 0){\n            for(Map.Entry<String,String> params:mHeaderParamsMap.entrySet()){\n                requestBuilder.header(params.getKey(),params.getValue());\n            }\n        }\n\n        Request newRequest = requestBuilder.build();\n\n        return chain.proceed(newRequest);\n    }\n\n    public static class Builder{\n        HttpCommonInterceptor mHttpCommonInterceptor;\n\n        public Builder(){\n            mHttpCommonInterceptor = new HttpCommonInterceptor();\n        }\n\n        public Builder addHeaderParams(String key, String value){\n            mHttpCommonInterceptor.mHeaderParamsMap.put(key,value);\n            return this;\n        }\n\n        public Builder  addHeaderParams(String key, int value){\n            return addHeaderParams(key, String.valueOf(value));\n        }\n\n        public Builder  addHeaderParams(String key, float value){\n            return addHeaderParams(key, String.valueOf(value));\n        }\n\n        public Builder  addHeaderParams(String key, long value){\n            return addHeaderParams(key, String.valueOf(value));\n        }\n\n        public Builder  addHeaderParams(String key, double value){\n            return addHeaderParams(key, String.valueOf(value));\n        }\n\n\n        public HttpCommonInterceptor build(){\n            return mHttpCommonInterceptor;\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/api/HuobiService.java",
    "content": "package com.tophold.example.demo.kview.btc.api;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport io.reactivex.Observable;\nimport retrofit2.http.GET;\nimport retrofit2.http.QueryMap;\nimport com.tophold.example.demo.kview.btc.model.HuobiData;\nimport com.tophold.example.demo.kview.btc.model.HuobiSymbol;\nimport com.tophold.example.demo.kview.btc.model.HuobiQuote;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 11:31\n * 描 述 ：\n * ============================================================\n **/\npublic interface HuobiService {\n    @GET(\"/market/history/kline\")\n    Observable<HuobiData<List<HuobiQuote>>> chartQuotes(@QueryMap Map<String, Object> params);\n\n    @GET(\"/v1/common/symbols\")\n    Observable<HuobiData<List<HuobiSymbol>>> getSymbolList(@QueryMap Map<String, Object> params);\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/api/HuobiSocketApi.java",
    "content": "package com.tophold.example.demo.kview.btc.api;\n\nimport android.util.Log;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 21:31\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiSocketApi {\n    public static final String TAG = HuobiSocketApi.class.getSimpleName();\n\n    public static void ping(long time) {\n        String str = \"{\\\"ping\\\":\" + time + \"}\";\n        sendService(str);\n    }\n\n    public static void pong(long time) {\n        String str = \"{\\\"pong\\\":\" + time + \"}\";\n        sendService(str);\n    }\n\n    /**\n     * 订阅KLine和取消KLine\n     *\n     * @param id     一个唯一值，建议用时间戳\n     * @param symbol\n     * @param period 周期，不管任何周期，全部转化为时间戳格式\n     * @param sub    true:订阅；false:取消订阅\n     */\n    public static void kLine(long id, String symbol, long period, boolean sub) {\n        String periodByMs = getPeriodByMs(period);\n        if (periodByMs == null) {\n            Log.e(TAG, \"subKLine: period 不合法！！！\");\n            return;\n        }\n        String kline = \"market.\" + symbol + \".kline.\" + periodByMs;\n        String json = \"{\" + (sub ? \"\\\"sub\\\"\" : \"\\\"unsub\\\"\") + \":\\\"\" + kline + \"\\\",\\\"id\\\":\\\"\" + id + \"\\\"}\";\n\n        sendService(json);\n\n    }\n\n    public static void subKLine(String symbol, long period, boolean sub) {\n        long id = System.currentTimeMillis();\n        kLine(id, symbol, period, sub);\n    }\n\n    private static void sendService(String str) {\n        Log.d(TAG, \"sendService: \" + str);\n        HuobiWebSocket.getInstance().getWebSocket().send(str);\n    }\n\n    private static String getPeriodByMs(long ms) {\n        long s = ms / 1000;\n        if (s == 1 * 60) return \"1min\";\n        if (s == 5 * 60) return \"5min\";\n        if (s == 15 * 60) return \"15min\";\n        if (s == 30 * 60) return \"30min\";\n        if (s == 60 * 60) return \"60min\";\n        if (s == 24 * 60 * 60) return \"1day\";\n        if (s == 7 * 24 * 60 * 60) return \"1week\";\n        if (s == 30 * 24 * 60 * 60) return \"1mon\";\n        if (s == 365 * 24 * 60 * 60) return \"1year\";\n        Log.d(TAG, \"getPeriodByMs: unkonwn ms!!！\");\n        return null;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/api/HuobiSocketParser.java",
    "content": "package com.tophold.example.demo.kview.btc.api;\n\nimport android.util.Log;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport com.tophold.example.demo.kview.btc.model.HuobiWsQuote;\nimport com.tophold.example.utils.GsonUtil;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 21:26\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiSocketParser {\n    public static final String TAG = HuobiSocketParser.class.getSimpleName();\n\n    public static void fix2Object(String str) {\n        Log.d(TAG, \"fix2Object: \" + str);\n        try {\n            formatJson(str);\n        } catch (JSONException e) {\n            e.printStackTrace();\n        }\n    }\n\n    private static void formatJson(String str) throws JSONException {\n        JSONObject json = new JSONObject(str);\n        if (json.has(\"ping\")) {\n            long ping = json.getLong(\"ping\");\n            HuobiSocketApi.pong(ping);\n            return;\n        }\n\n        //判断不严谨\n        if (json.has(\"ch\")) {\n            HuobiWsQuote huobiWsQuote = GsonUtil.fromJson2Object(str, HuobiWsQuote.class);\n            if (huobiWsQuote != null) {\n                obj2EventBus(huobiWsQuote);\n            }\n            return;\n        }\n\n    }\n\n    private static void obj2EventBus(Object object) {\n        EventBus.getDefault().post(object);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/api/HuobiWebSocket.java",
    "content": "package com.tophold.example.demo.kview.btc.api;\n\nimport android.support.annotation.Nullable;\nimport android.util.Log;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\n\nimport okhttp3.OkHttpClient;\nimport okhttp3.Request;\nimport okhttp3.Response;\nimport okhttp3.WebSocket;\nimport okhttp3.WebSocketListener;\nimport okhttp3.logging.HttpLoggingInterceptor;\nimport okio.ByteString;\nimport com.tophold.example.BuildConfig;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 21:15\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiWebSocket {\n    public static final String TAG = HuobiWebSocket.class.getSimpleName();\n    private static final int DEFAULT_TIME_OUT = 20;//超时时间 5s\n    private static final int DEFAULT_READ_TIME_OUT = 20;\n    //temp quotes\n    private static final String BASE_URL = \"https://api.huobi.br.com:443/ws\";\n\n    Request mRequest;\n    private okhttp3.WebSocket mWebSocket;\n    OkHttpClient client;\n    boolean isConnctted = false;\n\n    public WebSocket getWebSocket() {\n        return mWebSocket;\n    }\n\n    private HuobiWebSocket() {\n        // 创建 OKHttpClient\n        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();\n        builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间\n        builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间\n        builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间\n        builder.pingInterval(5000, TimeUnit.MILLISECONDS);\n        builder.retryOnConnectionFailure(true);//失败重试\n\n        //DEBUG模式下 添加日志拦截器\n        if (BuildConfig.DEBUG) {\n            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();\n            interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);\n            builder.addInterceptor(interceptor);\n        }\n\n        // 添加公共参数拦截器\n        HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()\n                .addHeaderParams(\"paltform\", \"android\")\n                .addHeaderParams(\"userToken\", \"1234343434dfdfd3434\")\n                .addHeaderParams(\"userId\", \"123445\")\n                .build();\n        //builder.addInterceptor(commonInterceptor);\n\n\n        //HuobiWebSocket\n        client = builder.build();\n    }\n\n    public void init() {\n        mRequest = new Request.Builder().url(BASE_URL).build();\n        mWebSocket = client.newWebSocket(mRequest, new WebSocketListener() {\n            @Override\n            public void onOpen(okhttp3.WebSocket webSocket, Response response) {\n                super.onOpen(webSocket, response);\n                isConnctted = true;\n                Log.d(TAG, \"onOpen: \");\n                //Toast.makeText(MyApplication.mAppContext, \"websocket连接成功...\", Toast.LENGTH_SHORT).show();\n            }\n\n            @Override\n            public void onMessage(okhttp3.WebSocket webSocket, String text) {\n                super.onMessage(webSocket, text);\n                Log.d(TAG, \"onMessage: \" + text);\n                HuobiSocketParser.fix2Object(text);\n            }\n\n            @Override\n            public void onMessage(WebSocket webSocket, ByteString bytes) {\n                super.onMessage(webSocket, bytes);\n                String s = null;\n                try {\n                    s = GZipUtil.uncompressBytes(bytes.toByteArray());\n                    HuobiSocketParser.fix2Object(s);\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n\n            @Override\n            public void onClosed(okhttp3.WebSocket webSocket, int code, String reason) {\n                super.onClosed(webSocket, code, reason);\n                isConnctted = false;\n                Log.d(TAG, \"onClosed,code: \" + code + \",reason:\" + reason);\n                //Toast.makeText(MyApplication.mAppContext, \"websocket关闭...\", Toast.LENGTH_SHORT).show();\n            }\n\n            @Override\n            public void onFailure(okhttp3.WebSocket webSocket, Throwable t, @Nullable Response response) {\n                super.onFailure(webSocket, t, response);\n                isConnctted = false;\n                Log.e(TAG, \"onFailure: \" + (response != null ? response.toString() : \"response==null\"));\n                t.printStackTrace();\n            }\n        });\n    }\n\n    private static class SingletonHolder {\n        private static final HuobiWebSocket INSTANCE = new HuobiWebSocket();\n    }\n\n    /**\n     * 获取RetrofitServiceManager\n     *\n     * @return\n     */\n    public static HuobiWebSocket getInstance() {\n        return HuobiWebSocket.SingletonHolder.INSTANCE;\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/api/RetrofitManager.java",
    "content": "package com.tophold.example.demo.kview.btc.api;\n\n\nimport java.util.concurrent.TimeUnit;\n\nimport io.reactivex.Observable;\nimport io.reactivex.Observer;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.schedulers.Schedulers;\nimport okhttp3.OkHttpClient;\nimport okhttp3.logging.HttpLoggingInterceptor;\nimport retrofit2.Retrofit;\nimport retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport retrofit2.converter.gson.GsonConverterFactory;\nimport com.tophold.example.BuildConfig;\n\n\npublic class RetrofitManager {\n    private static final int DEFAULT_TIME_OUT = 20;//超时时间 5s\n    private static final int DEFAULT_READ_TIME_OUT = 20;\n    //temp quotes\n//    private static final String BASE_URL = \"https://api.huobipro.com\";\n    private static final String BASE_URL = \"https://api.huobi.br.com\";\n    private Retrofit mRetrofit;\n\n    private RetrofitManager() {\n        // 创建 OKHttpClient\n        OkHttpClient.Builder builder = new OkHttpClient.Builder();\n        builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间\n        builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间\n        builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间\n        builder.retryOnConnectionFailure(true);//失败重试\n\n        //DEBUG模式下 添加日志拦截器\n        if (BuildConfig.DEBUG) {\n            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();\n            interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);\n            builder.addInterceptor(interceptor);\n        }\n\n        // 添加公共参数拦截器\n        HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()\n                .addHeaderParams(\"paltform\", \"android\")\n                .addHeaderParams(\"userToken\", \"1234343434dfdfd3434\")\n                .addHeaderParams(\"userId\", \"123445\")\n                .build();\n        //builder.addInterceptor(commonInterceptor);\n\n\n        // 创建Retrofit\n        mRetrofit = new Retrofit.Builder()\n                .baseUrl(BASE_URL)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))\n                .addConverterFactory(GsonConverterFactory.create())\n                .client(builder.build())\n                .build();\n    }\n\n    private static class SingletonHolder {\n        private static final RetrofitManager INSTANCE = new RetrofitManager();\n    }\n\n    /**\n     * 获取RetrofitServiceManager\n     *\n     * @return\n     */\n    public static RetrofitManager getInstance() {\n        return SingletonHolder.INSTANCE;\n    }\n\n    /**\n     * 获取对应的Service\n     *\n     * @param service Service 的 class\n     * @param <T>\n     * @return\n     */\n    public <T> T create(Class<T> service) {\n        return mRetrofit.create(service);\n    }\n\n    public static Observable call(Observable<?> observable, Observer observer) {\n        observable.subscribeOn(Schedulers.io())\n                .unsubscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(observer);\n        return observable;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/model/HuobiData.java",
    "content": "package com.tophold.example.demo.kview.btc.model;\n\nimport java.io.Serializable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/26 13:29\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiData<T> implements Serializable{\n    public String status;\n    public String ch;\n    public long ts;\n    public T data;\n\n    @Override\n    public String toString() {\n        return \"HuobiData{\" +\n                \"status='\" + status + '\\'' +\n                \", ch='\" + ch + '\\'' +\n                \", ts=\" + ts +\n                \", data=\" + data +\n                '}';\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/model/HuobiQuote.java",
    "content": "package com.tophold.example.demo.kview.btc.model;\n\nimport java.io.Serializable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/26 13:31\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiQuote implements Serializable{\n    public long id;\n    public double open;\n    public double close;\n    public double low;\n    public double high;\n    public double amount;\n    public double vol;\n    public double count;\n\n    @Override\n    public String toString() {\n        return \"HuobiQuote{\" +\n                \"id='\" + id + '\\'' +\n                \", open=\" + open +\n                \", close=\" + close +\n                \", low=\" + low +\n                \", high=\" + high +\n                \", amount=\" + amount +\n                \", vol=\" + vol +\n                \", count=\" + count +\n                '}';\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/model/HuobiSymbol.java",
    "content": "package com.tophold.example.demo.kview.btc.model;\n\nimport com.google.gson.annotations.SerializedName;\n\nimport java.io.Serializable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/26 13:42\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiSymbol implements Serializable {\n    @SerializedName(\"base-currency\")\n    public String base_currency;\n    @SerializedName(\"quote-currency\")\n    public String quote_currency;\n    @SerializedName(\"price-precision\")\n    public int price_precision;\n    @SerializedName(\"amount-precision\")\n    public int amount_precision;\n    @SerializedName(\"symbol-partition\")\n    public String symbol_partition;\n\n    public HuobiSymbol(String base_currency, String quote_currency, int price_precision, int amount_precision, String symbol_partition) {\n        this.base_currency = base_currency;\n        this.quote_currency = quote_currency;\n        this.price_precision = price_precision;\n        this.amount_precision = amount_precision;\n        this.symbol_partition = symbol_partition;\n    }\n\n    @Override\n    public String toString() {\n        return \"HuobiSymbol{\" +\n                \"base_currency='\" + base_currency + '\\'' +\n                \", quote_currency='\" + quote_currency + '\\'' +\n                \", price_precision=\" + price_precision +\n                \", amount_precision=\" + amount_precision +\n                \", symbol_partition='\" + symbol_partition + '\\'' +\n                '}';\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/model/HuobiTab.java",
    "content": "package com.tophold.example.demo.kview.btc.model;\n\nimport java.io.Serializable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/26 16:07\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiTab implements Serializable {\n    public HuobiTab.HuobiType mForexType;\n    public String tabName;\n\n    public HuobiTab(HuobiTab.HuobiType forexType, String tabName) {\n        this.mForexType = forexType;\n        this.tabName = tabName;\n    }\n\n    /**\n     * 获取对应类型的长度\n     *\n     * @return sencond\n     */\n    public long getTypeLength() {\n        long len = 0;\n        switch (mForexType) {\n            case _timeShring:\n                len = 60;\n                break;\n            case _1m:\n                len = 60;\n                break;\n            case _5m:\n                len = 5 * 60;\n                break;\n            case _15m:\n                len = 15 * 60;\n                break;\n            case _30m:\n                len = 30 * 60;\n                break;\n            case _60m:\n                len = 60 * 60;\n                break;\n            case _1d:\n                len = 24 * 60 * 60;\n                break;\n            case _1w:\n                len = 7 * 24 * 60 * 60;\n                break;\n            case _1mon:\n                len = 30 * 24 * 60 * 60;\n                break;\n            case _1y:\n                len = 365 * 24 * 60 * 60;\n                break;\n            default:\n                len = 60;\n                break;\n        }\n        return len;\n    }\n\n    /**\n     * 根据mForexType返回接口需要的类型字段\n     *\n     * @return\n     */\n    public String getType() {\n        String typeMsg = \"1min\";\n        switch (mForexType) {\n            case _timeShring:\n                typeMsg = \"1min\";\n                break;\n            case _1m:\n                typeMsg = \"1min\";\n                break;\n            case _5m:\n                typeMsg = \"5min\";\n                break;\n            case _15m:\n                typeMsg = \"15min\";\n                break;\n            case _30m:\n                typeMsg = \"30min\";\n                break;\n            case _60m:\n                typeMsg = \"60min\";\n                break;\n            case _1d:\n                typeMsg = \"1day\";\n                break;\n            case _1w:\n                typeMsg = \"1week\";\n                break;\n            case _1mon:\n                typeMsg = \"1mon\";\n                break;\n            case _1y:\n                typeMsg = \"1year\";\n                break;\n            default:\n                typeMsg = \"1min\";\n                break;\n        }\n        return typeMsg;\n    }\n\n    public enum HuobiType {\n        _timeShring,\n        _1m,\n        _5m,\n        _15m,\n        _30m,\n        _60m,\n        _1d,\n        _1w,\n        _1mon,\n        _1y\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/model/HuobiWsQuote.java",
    "content": "package com.tophold.example.demo.kview.btc.model;\n\nimport java.io.Serializable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/28 18:39\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiWsQuote implements Serializable{\n\n    /**\n     * ch : market.eosusdt.kline.1min\n     * ts : 1522233524438\n     * tick : {\"id\":1522233480,\"open\":6.317,\"close\":6.3216,\"low\":6.3091,\"high\":6.3216,\"amount\":2024.6227,\"vol\":12789.80758224,\"count\":21}\n     */\n\n    public String ch;\n    public long ts;\n    public TickBean tick;\n\n    public static class TickBean {\n        /**\n         * id : 1522233480\n         * open : 6.317\n         * close : 6.3216\n         * low : 6.3091\n         * high : 6.3216\n         * amount : 2024.6227\n         * vol : 12789.80758224\n         * count : 21\n         */\n\n        public int id;\n        public double open;\n        public double close;\n        public double low;\n        public double high;\n        public double amount;\n        public double vol;\n        public int count;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/ui/HuobiActivity.java",
    "content": "package com.tophold.example.demo.kview.btc.ui;\n\nimport android.content.pm.ActivityInfo;\nimport android.os.Bundle;\nimport android.support.annotation.ColorRes;\nimport android.support.design.widget.TabLayout;\nimport android.support.v4.app.Fragment;\nimport android.view.View;\nimport android.view.Window;\nimport android.view.WindowManager;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.tophold.example.base.BaseActivity;\nimport com.tophold.example.utils.NoScrollViewPager;\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.btc.model.HuobiSymbol;\nimport com.tophold.example.demo.kview.btc.model.HuobiTab;\nimport com.tophold.trade.utils.FormatUtil;\nimport com.tophold.trade.utils.TimeUtils;\nimport com.tophold.trade.view.kview.Quotes;\n\npublic class HuobiActivity extends BaseActivity {\n    public static final String KEY_FOREX = \"KEY_FOREX\";\n    public static final String KEY_HORIZONTAL = \"KEY_HORIZONTAL\";\n    private TabLayout mAfTlTablayout;\n    private NoScrollViewPager mAfVpViewpager;\n\n    private LinearLayout mAkvLlContainer;\n    private TextView mAkvTvH;\n    private TextView mAkvTvO;\n    private TextView mAkvTvTime;\n    private TextView mAkvTvL;\n    private TextView mAkvTvC;\n    private TextView mAkvTvP;\n    private TextView af_tv_symbol;\n    private TextView mAkvTvBlank;\n\n    //是否是横屏\n    boolean mIsHorizontal = false;\n\n    private List<HuobiTab> mForexTabList;\n    private List<Fragment> mKViewFragmentList;\n\n    HuobiSymbol mForex;\n\n    @Override\n    protected void getBundleExtras(Bundle extras) {\n        super.getBundleExtras(extras);\n        mForex = (HuobiSymbol) extras.getSerializable(KEY_FOREX);\n        mIsHorizontal = extras.getBoolean(KEY_HORIZONTAL);\n    }\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        if (mIsHorizontal) {\n            requestWindowFeature(Window.FEATURE_NO_TITLE);// 隐藏标题\n            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,\n\n                    WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏\n        }\n        setContentView(R.layout.activity_huobi);\n        initView();\n        initData();\n        initAdapter();\n        loadData();\n        initListener();\n    }\n\n    @Override\n    protected void onResume() {\n        if (mIsHorizontal) {\n            if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {\n                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);\n            }\n        }\n        super.onResume();\n    }\n\n    private void initView() {\n        mAfTlTablayout = (TabLayout) findViewById(R.id.af_tl_tablayout);\n        mAfVpViewpager = (NoScrollViewPager) findViewById(R.id.af_vp_viewpager);\n\n        mAkvLlContainer = (LinearLayout) findViewById(R.id.akv_ll_container);\n        mAkvTvH = (TextView) findViewById(R.id.akv_tv_h);\n        mAkvTvO = (TextView) findViewById(R.id.akv_tv_o);\n        mAkvTvTime = (TextView) findViewById(R.id.akv_tv_time);\n        mAkvTvL = (TextView) findViewById(R.id.akv_tv_l);\n        mAkvTvC = (TextView) findViewById(R.id.akv_tv_c);\n        mAkvTvP = (TextView) findViewById(R.id.akv_tv_p);\n        mAkvTvBlank = (TextView) findViewById(R.id.af_tv_blank);\n        af_tv_symbol = (TextView) findViewById(R.id.af_tv_symbol);\n\n        if (mIsHorizontal) {\n            af_tv_symbol.setVisibility(View.GONE);\n            mAkvTvBlank.setVisibility(View.GONE);\n        } else {\n            af_tv_symbol.setVisibility(View.VISIBLE);\n            mAkvTvBlank.setVisibility(View.VISIBLE);\n            af_tv_symbol.setText(mForex.base_currency + \"/\" + mForex.quote_currency);\n        }\n\n    }\n\n    private void initData() {\n        mForexTabList = new ArrayList<>();\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._timeShring, \"分时\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1m, \"1分\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._5m, \"5分\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._15m, \"15分\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._30m, \"30分\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._60m, \"1小时\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1d, \"日K\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1w, \"周K\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1mon, \"月K\"));\n        mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1y, \"年K\"));\n\n        mAfTlTablayout.setTabMode(TabLayout.MODE_SCROLLABLE);\n\n        mKViewFragmentList = new ArrayList<>();\n        for (HuobiTab forexTab : mForexTabList) {\n            mKViewFragmentList.add(HuobiFragment.newInstance(forexTab, mForex));\n        }\n    }\n\n    private void initAdapter() {\n        mAfVpViewpager.setAdapter(new HuobiAdapter(getSupportFragmentManager(), mKViewFragmentList, mForexTabList));\n        mAfTlTablayout.setupWithViewPager(mAfVpViewpager);\n    }\n\n    private void loadData() {\n\n    }\n\n    private void initListener() {\n\n    }\n\n\n    public void hidenContainer() {\n        mAfTlTablayout.setVisibility(View.VISIBLE);\n        mAkvLlContainer.setVisibility(View.GONE);\n    }\n\n    public void showContanier(Quotes preQuotes, Quotes currentQuotes) {\n        mAfTlTablayout.setVisibility(View.GONE);\n        mAkvLlContainer.setVisibility(View.VISIBLE);\n        int digits = 5;\n        boolean isPositive;\n        String precent;\n        double dis = (currentQuotes.c - preQuotes.c) / currentQuotes.c * 100;\n        isPositive = dis >= 0;\n        precent = FormatUtil.formatBySubString(dis, 2);\n        precent += \"%\";\n\n        //\n        mAkvTvH.setText(FormatUtil.numFormat(currentQuotes.h, digits));\n        mAkvTvO.setText(FormatUtil.numFormat(currentQuotes.o, digits));\n        mAkvTvL.setText(FormatUtil.numFormat(currentQuotes.l, digits));\n        mAkvTvC.setText(FormatUtil.numFormat(currentQuotes.c, digits));\n        mAkvTvP.setText(precent);\n        mAkvTvTime.setText(TimeUtils.millis2String(currentQuotes.t, new SimpleDateFormat(\"MM-dd HH:mm\")));\n\n        if (isPositive) {\n            mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n        } else {\n            mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n        }\n    }\n\n    private int getMyColor(@ColorRes int colorId) {\n        return getResources().getColor(colorId);\n    }\n\n    public void showHorizontal(View view) {\n        Bundle bundle = new Bundle();\n        bundle.putBoolean(KEY_HORIZONTAL, true);\n        bundle.putSerializable(KEY_FOREX, mForex);\n        go(HuobiActivity.class, bundle);\n    }\n\n    public boolean isHorizontal() {\n        return mIsHorizontal;\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/ui/HuobiAdapter.java",
    "content": "package com.tophold.example.demo.kview.btc.ui;\n\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentManager;\nimport android.support.v4.app.FragmentPagerAdapter;\n\nimport java.util.List;\n\nimport com.tophold.example.demo.kview.btc.model.HuobiTab;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/26 13:37\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiAdapter extends FragmentPagerAdapter {\n    private List<Fragment> mFragmentList;\n    List<HuobiTab> mForexTabList;\n\n    public HuobiAdapter(FragmentManager fm, List<Fragment> fragmentList, List<HuobiTab> mForexTabList) {\n        super(fm);\n        this.mFragmentList = fragmentList;\n        this.mForexTabList = mForexTabList;\n    }\n\n\n    @Override\n    public Fragment getItem(int position) {\n        return mFragmentList.get(position);\n    }\n\n    @Override\n    public int getCount() {\n        return mFragmentList.size();\n    }\n\n    @Override\n    public CharSequence getPageTitle(int position) {\n        return mForexTabList.get(position).tabName;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/ui/HuobiFragment.java",
    "content": "package com.tophold.example.demo.kview.btc.ui;\n\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Toast;\n\nimport org.greenrobot.eventbus.Subscribe;\nimport org.greenrobot.eventbus.ThreadMode;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport io.reactivex.Observer;\nimport io.reactivex.disposables.Disposable;\n\nimport com.tophold.example.base.BaseFragment;\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.btc.api.HuobiService;\nimport com.tophold.example.demo.kview.btc.api.HuobiSocketApi;\nimport com.tophold.example.demo.kview.btc.api.RetrofitManager;\nimport com.tophold.example.demo.kview.btc.model.HuobiData;\nimport com.tophold.example.demo.kview.btc.model.HuobiQuote;\nimport com.tophold.example.demo.kview.btc.model.HuobiSymbol;\nimport com.tophold.example.demo.kview.btc.model.HuobiTab;\nimport com.tophold.example.demo.kview.btc.model.HuobiWsQuote;\nimport com.tophold.trade.utils.StringUtils;\nimport com.tophold.trade.view.kview.KView;\nimport com.tophold.trade.view.kview.KViewListener;\nimport com.tophold.trade.view.kview.Quotes;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/26 13:36\n * 描 述 ：\n * ============================================================\n **/\npublic class HuobiFragment extends BaseFragment {\n    public static final int DEF_PAGER_SIZE = 1000;\n    private static final String ARG_PARAM1 = \"param1\";\n    private static final String ARG_PARAM2 = \"param2\";\n    public static final int DEF_COUNT = 100;\n    private View mRootView;\n    private KView mFkKvKview;\n    HuobiTab mForexTab;\n    HuobiSymbol mForex;\n\n    //net\n    List<Quotes> mQuotesList;\n\n    public HuobiFragment() {\n\n    }\n\n    public static HuobiFragment newInstance(HuobiTab mForexTab, HuobiSymbol forex) {\n        HuobiFragment fragment = new HuobiFragment();\n        Bundle args = new Bundle();\n        args.putSerializable(ARG_PARAM1, mForexTab);\n        args.putSerializable(ARG_PARAM2, forex);\n        fragment.setArguments(args);\n        return fragment;\n    }\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        if (getArguments() != null) {\n            mForexTab = (HuobiTab) getArguments().getSerializable(ARG_PARAM1);\n            mForex = (HuobiSymbol) getArguments().getSerializable(ARG_PARAM2);\n        }\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        mRootView = inflater.inflate(R.layout.fragment_huobi, container, false);\n        initView();\n        initData();\n        initAdapter();\n        loadData();\n        initListener();\n        return mRootView;\n    }\n\n    private void loadData() {\n        loadKLineData(null, false);\n\n        subKLineData();\n    }\n\n    private void subKLineData() {\n        HuobiSocketApi.subKLine(mForex.base_currency + mForex.quote_currency, mForexTab.getTypeLength() * 1000, true);\n    }\n\n    private void initView() {\n        mFkKvKview = (KView) mRootView.findViewById(R.id.fk_kv_kview);\n\n        mFkKvKview.setDigit(5);\n\n        if (mForexTab.mForexType == HuobiTab.HuobiType._timeShring) {\n            mFkKvKview.setShowTimSharing(true);\n        } else {\n            mFkKvKview.setShowTimSharing(false);\n        }\n\n        if (((HuobiActivity) getActivity()).isHorizontal()) {\n            mFkKvKview.setShowMinor(true);\n            mFkKvKview.setShowVol(true);\n        } else {\n            mFkKvKview.setShowMinor(false);\n            mFkKvKview.setShowVol(false);\n        }\n    }\n\n    private void initData() {\n        mQuotesList = new ArrayList<>();\n    }\n\n    private void initAdapter() {\n\n    }\n\n    private void loadKLineData(String start_time, final boolean isLoadMore) {\n        Map<String, Object> map = new HashMap<>();\n        String symbol = mForex.base_currency + \"\" + mForex.quote_currency;\n        map.put(\"symbol\", symbol);\n        map.put(\"period\", mForexTab.getType());\n        map.put(\"size\", DEF_PAGER_SIZE);\n        //if (start_time != null) map.put(\"st\", start_time);\n        call(RetrofitManager.getInstance().create(HuobiService.class).chartQuotes(map), new Observer<HuobiData<List<HuobiQuote>>>() {\n            @Override\n            public void onSubscribe(Disposable d) {\n                unSubscription(d);\n            }\n\n            @Override\n            public void onNext(HuobiData<List<HuobiQuote>> huobiData) {\n\n                String status = huobiData.status;\n                if (!\"ok\".equals(status)) {\n                    Toast.makeText(mContext, \"数据获取失败...\", Toast.LENGTH_SHORT).show();\n                    return;\n                }\n                List<HuobiQuote> data = huobiData.data;\n                if (StringUtils.isEmpty(data)) {\n                    Toast.makeText(mContext, \"数据为空...\", Toast.LENGTH_SHORT).show();\n                    return;\n                }\n                adapterData(data);\n\n                drawKView(isLoadMore);\n            }\n\n            @Override\n            public void onError(Throwable e) {\n                e.printStackTrace();\n            }\n\n            @Override\n            public void onComplete() {\n\n            }\n        });\n    }\n\n    private void drawKView(boolean isLoadMore) {\n        if (!isLoadMore) {\n            mFkKvKview.setKViewData(mQuotesList, new KViewListener.MasterTouchListener() {\n                @Override\n                public void onLongTouch(Quotes preQuotes, Quotes currentQuotes) {\n                    ((HuobiActivity) getActivity()).showContanier(preQuotes, currentQuotes);\n                }\n\n                @Override\n                public void onUnLongTouch() {\n                    ((HuobiActivity) getActivity()).hidenContainer();\n                }\n\n                @Override\n                public void needLoadMore() {\n                    if (StringUtils.isEmpty(mQuotesList)) {\n                        mFkKvKview.loadMoreNoData();\n                        return;\n                    }\n                    Quotes quotes = mQuotesList.get(0);\n                    String showTime = quotes.getShowTime();\n                    //loadKLineData(showTime, true);火币不支持分页\n                }\n            });\n        } else {\n            mFkKvKview.loadKViewData(mQuotesList);\n        }\n    }\n\n    private void adapterData(List<HuobiQuote> huobiQuoteList) {\n\n        Collections.reverse(huobiQuoteList);\n\n        List<Quotes> quotesList = new ArrayList<>();\n        for (HuobiQuote huobiQuote : huobiQuoteList) {\n            Quotes quotes = new Quotes(huobiQuote.open, huobiQuote.high, huobiQuote.low, huobiQuote.close, huobiQuote.id * 1000, huobiQuote.amount);\n            quotesList.add(quotes);\n        }\n        mQuotesList.addAll(0, quotesList);//注意时序问题\n    }\n\n    private void initListener() {\n    }\n\n    @Override\n    public boolean isBindEventBusHere() {\n        return true;\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onReviceWsQuotes(HuobiWsQuote huobiWsQuote) {\n        if (huobiWsQuote == null || huobiWsQuote.tick == null) return;\n        //返回的数据真实醉了。。。\n        String ch = huobiWsQuote.ch;\n        String[] split = ch.split(\"\\\\.\");\n        String symbol = split[1];\n        String lineType = split[3];\n        if (!symbol.equals(mForex.base_currency + mForex.quote_currency)) return;\n        if (!lineType.equals(mForexTab.getType())) return;\n        HuobiWsQuote.TickBean tick = huobiWsQuote.tick;\n        Quotes quotes = new Quotes(tick.open, tick.high, tick.low, tick.close, huobiWsQuote.ts);\n\n        mFkKvKview.pushKViewData(quotes, mForexTab.getTypeLength() * 1000);\n    }\n\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        HuobiSocketApi.subKLine(mForex.base_currency + mForex.quote_currency, mForexTab.getTypeLength() * 1000, false);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/btc/ui/HuobiListActivity.java",
    "content": "package com.tophold.example.demo.kview.btc.ui;\n\nimport android.os.Bundle;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.util.Log;\nimport android.widget.Toast;\n\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.chad.library.adapter.base.BaseViewHolder;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport io.reactivex.Observer;\nimport io.reactivex.disposables.Disposable;\n\nimport com.tophold.example.base.BaseActivity;\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.btc.api.HuobiService;\nimport com.tophold.example.demo.kview.btc.api.RetrofitManager;\nimport com.tophold.example.demo.kview.btc.model.HuobiData;\nimport com.tophold.example.demo.kview.btc.model.HuobiSymbol;\nimport com.tophold.trade.utils.StringUtils;\n\npublic class HuobiListActivity extends BaseActivity {\n\n    RecyclerView mAflRlListview;\n    BaseQuickAdapter<HuobiSymbol, BaseViewHolder> mQuickAdapter;\n    List<HuobiSymbol> mForexList;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_huobi_list);\n        initView();\n        initData();\n        initAdapter();\n        loadData();\n        initListener();\n    }\n\n    private void initView() {\n        mAflRlListview = (RecyclerView) findViewById(R.id.afl_rl_listview);\n        Toast.makeText(mContext, \"请稍后，在拉取列表...\", Toast.LENGTH_SHORT).show();\n    }\n\n    private void initData() {\n        mForexList = new ArrayList<>();\n    }\n\n    private void initAdapter() {\n        mQuickAdapter = new BaseQuickAdapter<HuobiSymbol, BaseViewHolder>(R.layout.item_activity_huobi_list, mForexList) {\n            @Override\n            protected void convert(BaseViewHolder helper, HuobiSymbol item) {\n                helper.setText(R.id.iafl_tv_znName, item.base_currency + \"/\" + item.quote_currency);\n                helper.setText(R.id.iafl_tv_enName, item.quote_currency);\n                helper.setText(R.id.iafl_tv_part, item.symbol_partition);\n            }\n        };\n        mAflRlListview.setLayoutManager(new LinearLayoutManager(mContext));\n        mAflRlListview.setAdapter(mQuickAdapter);\n    }\n\n    private void loadData() {\n        Map<String, Object> map = new HashMap<>();\n        call(RetrofitManager.getInstance().create(HuobiService.class).getSymbolList(map), new Observer<HuobiData<List<HuobiSymbol>>>() {\n            @Override\n            public void onSubscribe(Disposable d) {\n                unSubscription(d);\n            }\n\n            @Override\n            public void onNext(HuobiData<List<HuobiSymbol>> huobiData) {\n                String status = huobiData.status;\n                if (!\"ok\".equals(status)) {\n                    Toast.makeText(mContext, \"数据获取失败...\", Toast.LENGTH_SHORT).show();\n                    return;\n                }\n                List<HuobiSymbol> data = huobiData.data;\n                if (StringUtils.isEmpty(data)) {\n                    Toast.makeText(mContext, \"数据为空...\", Toast.LENGTH_SHORT).show();\n                    return;\n                }\n                mForexList.addAll(data);\n\n                //排序操作\n                Collections.sort(mForexList, (o1, o2) -> {\n                    if (!o1.symbol_partition.equals(o2.symbol_partition))\n                        return -o1.symbol_partition.compareTo(o2.symbol_partition);\n                    if (!o1.quote_currency.equals(o2.quote_currency))\n                        return -o1.quote_currency.compareTo(o2.quote_currency);\n                    return 0;\n                });\n\n                mQuickAdapter.notifyLoadMoreToLoading();\n            }\n\n            @Override\n            public void onError(Throwable e) {\n                e.printStackTrace();\n            }\n\n            @Override\n            public void onComplete() {\n                Log.d(TAG, \"onComplete: \");\n            }\n        });\n    }\n\n    private void initListener() {\n        mQuickAdapter.setOnItemClickListener((adapter, v, p) -> {\n            HuobiSymbol forex = mForexList.get(p);\n            Bundle bundle = new Bundle();\n            bundle.putSerializable(HuobiActivity.KEY_FOREX, forex);\n            go(HuobiActivity.class, bundle);\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/ForexTab.java",
    "content": "package com.tophold.example.demo.kview.forex;\n\nimport java.io.Serializable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 14:16\n * 描 述 ：\n * ============================================================\n **/\npublic class ForexTab implements Serializable {\n    public ForexType mForexType;\n    public String tabName;\n\n    public ForexTab(ForexType forexType, String tabName) {\n        this.mForexType = forexType;\n        this.tabName = tabName;\n    }\n\n    /**\n     * 获取对应类型的长度\n     *\n     * @return sencond\n     */\n    public long getTypeLength() {\n        long len = 0;\n        switch (mForexType) {\n            case _timeShring:\n                len = 60;\n                break;\n            case _1m:\n                len = 60;\n                break;\n            case _5m:\n                len = 5 * 60;\n                break;\n            case _15m:\n                len = 15 * 60;\n                break;\n            case _30m:\n                len = 30 * 60;\n                break;\n            case _1h:\n                len = 60 * 60;\n                break;\n            case _4h:\n                len = 4 * 60 * 60;\n                break;\n            case _1d:\n                len = 24 * 60 * 60;\n                break;\n            case _1w:\n                len = 7 * 24 * 60 * 60;\n                break;\n            case _1mon:\n                len = 30 * 24 * 60 * 60;\n                break;\n            default:\n                len = 60;\n                break;\n        }\n        return len;\n    }\n\n    /**\n     * 根据mForexType返回接口需要的类型字段\n     *\n     * @return\n     */\n    public String getType() {\n        String typeMsg = \"1m\";\n        switch (mForexType) {\n            case _timeShring:\n                typeMsg = \"1m\";\n                break;\n            case _1m:\n                typeMsg = \"1m\";\n                break;\n            case _5m:\n                typeMsg = \"5m\";\n                break;\n            case _15m:\n                typeMsg = \"15m\";\n                break;\n            case _30m:\n                typeMsg = \"30m\";\n                break;\n            case _1h:\n                typeMsg = \"1h\";\n                break;\n            case _4h:\n                typeMsg = \"4h\";\n                break;\n            case _1d:\n                typeMsg = \"1d\";\n                break;\n            case _1w:\n                typeMsg = \"1w\";\n                break;\n            case _1mon:\n                typeMsg = \"1mon\";\n                break;\n            default:\n                typeMsg = \"1m\";\n                break;\n        }\n        return typeMsg;\n    }\n\n    public enum ForexType {\n        _timeShring,\n        _1m,\n        _5m,\n        _15m,\n        _30m,\n        _1h,\n        _4h,\n        _1d,\n        _1w,\n        _1mon\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/api/ForexWebSocket.java",
    "content": "package com.tophold.example.demo.kview.forex.api;\n\nimport android.support.annotation.Nullable;\nimport android.util.Log;\n\nimport java.util.concurrent.TimeUnit;\n\nimport okhttp3.OkHttpClient;\nimport okhttp3.Request;\nimport okhttp3.Response;\nimport okhttp3.WebSocketListener;\nimport okhttp3.logging.HttpLoggingInterceptor;\nimport com.tophold.example.BuildConfig;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 21:15\n * 描 述 ：\n * ============================================================\n **/\npublic class ForexWebSocket {\n    public static final String TAG = ForexWebSocket.class.getSimpleName();\n    private static final int DEFAULT_TIME_OUT = 5;//超时时间 5s\n    private static final int DEFAULT_READ_TIME_OUT = 10;\n    //temp quotes\n    private static final String BASE_URL = \"http://***:8990/websocket\";\n    private static final String TOKEN=\"eyJ0eXAiOiJKV1QiLCJhbGc***Y2NvdW50SWQiOiJFVVI2MTQxLjAwMSIsImlhdCI6MTUyMjgxOTE0NiwiZXhwIjoxNTIzNDIzOTQ2fQ.je5e76RSNh07ZYtu3_yOA8BsBl_wH0_tkqxlgX5hhww\";\n\n    Request mRequest;\n    okhttp3.WebSocket mWebSocket;\n    OkHttpClient client;\n    boolean isConnctted = false;\n\n    private ForexWebSocket() {\n        // 创建 OKHttpClient\n        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();\n        builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间\n        builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间\n        builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间\n        builder.retryOnConnectionFailure(true);//失败重试\n\n        //DEBUG模式下 添加日志拦截器\n        if (BuildConfig.DEBUG) {\n            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();\n            interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);\n            builder.addInterceptor(interceptor);\n        }\n\n        // 添加公共参数拦截器\n        HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()\n                .addHeaderParams(\"paltform\", \"android\")\n                .addHeaderParams(\"userToken\", \"1234343434dfdfd3434\")\n                .addHeaderParams(\"userId\", \"123445\")\n                .build();\n        builder.addInterceptor(commonInterceptor);\n\n\n        //HuobiWebSocket\n        client = builder.build();\n    }\n\n    public void init() {\n        mRequest = new Request.Builder().header(\"Sec-WebSocket-Protocol\", TOKEN).url(BASE_URL).build();\n        mWebSocket = client.newWebSocket(mRequest, new WebSocketListener() {\n            @Override\n            public void onOpen(okhttp3.WebSocket webSocket, Response response) {\n                super.onOpen(webSocket, response);\n                isConnctted = true;\n                Log.d(TAG, \"onOpen: \");\n                //Toast.makeText(MyApplication.mAppContext, \"websocket连接成功...\", Toast.LENGTH_SHORT).show();\n            }\n\n            @Override\n            public void onMessage(okhttp3.WebSocket webSocket, String text) {\n                super.onMessage(webSocket, text);\n                WebSocketParser.fix2Object(text);\n            }\n\n            @Override\n            public void onClosed(okhttp3.WebSocket webSocket, int code, String reason) {\n                super.onClosed(webSocket, code, reason);\n                isConnctted = false;\n                Log.d(TAG, \"onClosed,code: \" + code + \",reason:\" + reason);\n                //Toast.makeText(MyApplication.mAppContext, \"websocket关闭...\", Toast.LENGTH_SHORT).show();\n            }\n\n            @Override\n            public void onFailure(okhttp3.WebSocket webSocket, Throwable t, @Nullable Response response) {\n                super.onFailure(webSocket, t, response);\n                isConnctted = false;\n                //Toast.makeText(MyApplication.mAppContext, \"websocket异常：\" + response.toString(), Toast.LENGTH_SHORT).show();\n                Log.e(TAG, \"onFailure: \" + (response != null ? response.toString() : \"response==null\"));\n                t.printStackTrace();\n            }\n        });\n    }\n\n    private static class SingletonHolder {\n        private static final ForexWebSocket INSTANCE = new ForexWebSocket();\n    }\n\n    /**\n     * 获取RetrofitServiceManager\n     *\n     * @return\n     */\n    public static ForexWebSocket getInstance() {\n        return ForexWebSocket.SingletonHolder.INSTANCE;\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/api/HttpCommonInterceptor.java",
    "content": "package com.tophold.example.demo.kview.forex.api;\n\nimport android.util.Log;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport okhttp3.Interceptor;\nimport okhttp3.Request;\nimport okhttp3.Response;\n\n/**\n * 拦截器\n *\n * 向请求头里添加公共参数\n * Created by zhouwei on 16/11/10.\n */\n\npublic class HttpCommonInterceptor implements Interceptor {\n\n    private Map<String,String> mHeaderParamsMap = new HashMap<>();\n    public HttpCommonInterceptor() {\n\n    }\n\n    @Override\n    public Response intercept(Chain chain) throws IOException {\n        Log.d(\"HttpCommonInterceptor\",\"add common params\");\n        Request oldRequest = chain.request();\n\n        // 添加新的参数，添加到url 中\n       /* HttpUrl.Builder authorizedUrlBuilder = oldRequest.url()\n                .newBuilder()\n                .scheme(oldRequest.url().scheme())\n                .host(oldRequest.url().host());*/\n\n        // 新的请求\n\n        Request.Builder requestBuilder =  oldRequest.newBuilder();\n                requestBuilder.method(oldRequest.method(), oldRequest.body());\n        //添加公共参数,添加到header中\n        if(mHeaderParamsMap.size() > 0){\n            for(Map.Entry<String,String> params:mHeaderParamsMap.entrySet()){\n                requestBuilder.header(params.getKey(),params.getValue());\n            }\n        }\n\n        Request newRequest = requestBuilder.build();\n\n        return chain.proceed(newRequest);\n    }\n\n    public static class Builder{\n        HttpCommonInterceptor mHttpCommonInterceptor;\n\n        public Builder(){\n            mHttpCommonInterceptor = new HttpCommonInterceptor();\n        }\n\n        public Builder addHeaderParams(String key, String value){\n            mHttpCommonInterceptor.mHeaderParamsMap.put(key,value);\n            return this;\n        }\n\n        public Builder  addHeaderParams(String key, int value){\n            return addHeaderParams(key, String.valueOf(value));\n        }\n\n        public Builder  addHeaderParams(String key, float value){\n            return addHeaderParams(key, String.valueOf(value));\n        }\n\n        public Builder  addHeaderParams(String key, long value){\n            return addHeaderParams(key, String.valueOf(value));\n        }\n\n        public Builder  addHeaderParams(String key, double value){\n            return addHeaderParams(key, String.valueOf(value));\n        }\n\n\n        public HttpCommonInterceptor build(){\n            return mHttpCommonInterceptor;\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/api/RetrofitManager.java",
    "content": "package com.tophold.example.demo.kview.forex.api;\n\n\nimport java.util.concurrent.TimeUnit;\n\nimport io.reactivex.Observable;\nimport io.reactivex.Observer;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.schedulers.Schedulers;\nimport okhttp3.OkHttpClient;\nimport okhttp3.logging.HttpLoggingInterceptor;\nimport retrofit2.Retrofit;\nimport retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport retrofit2.converter.gson.GsonConverterFactory;\nimport com.tophold.example.BuildConfig;\n\n\npublic class RetrofitManager {\n    private static final int DEFAULT_TIME_OUT = 5;//超时时间 5s\n    private static final int DEFAULT_READ_TIME_OUT = 10;\n    //temp quotes\n    private static final String BASE_URL = \"http://***:8700/\";\n    private Retrofit mRetrofit;\n\n    private RetrofitManager() {\n        // 创建 OKHttpClient\n        OkHttpClient.Builder builder = new OkHttpClient.Builder();\n        builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间\n        builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间\n        builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间\n        builder.retryOnConnectionFailure(true);//失败重试\n\n        //DEBUG模式下 添加日志拦截器\n        if (BuildConfig.DEBUG) {\n            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();\n            interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);\n            builder.addInterceptor(interceptor);\n        }\n\n        // 添加公共参数拦截器\n        HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()\n                .addHeaderParams(\"paltform\", \"android\")\n                .addHeaderParams(\"userToken\", \"1234343434dfdfd3434\")\n                .addHeaderParams(\"userId\", \"123445\")\n                .build();\n        builder.addInterceptor(commonInterceptor);\n\n\n        // 创建Retrofit\n        mRetrofit = new Retrofit.Builder()\n                .baseUrl(BASE_URL)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))\n                .addConverterFactory(GsonConverterFactory.create())\n                .client(builder.build())\n                .build();\n    }\n\n    private static class SingletonHolder {\n        private static final RetrofitManager INSTANCE = new RetrofitManager();\n    }\n\n    /**\n     * 获取RetrofitServiceManager\n     *\n     * @return\n     */\n    public static RetrofitManager getInstance() {\n        return SingletonHolder.INSTANCE;\n    }\n\n    /**\n     * 获取对应的Service\n     *\n     * @param service Service 的 class\n     * @param <T>\n     * @return\n     */\n    public <T> T create(Class<T> service) {\n        return mRetrofit.create(service);\n    }\n\n    public static Observable call(Observable<?> observable, Observer observer) {\n        observable.subscribeOn(Schedulers.io())\n                .unsubscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe(observer);\n        return observable;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/api/WebSocketApi.java",
    "content": "package com.tophold.example.demo.kview.forex.api;\n\nimport android.util.Log;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 21:31\n * 描 述 ：\n * ============================================================\n **/\npublic class WebSocketApi {\n    public static final String TAG = WebSocketApi.class.getSimpleName();\n\n    /**\n     * 订阅价格和取消订阅\n     *\n     * @param isSub true:订阅，false:取消订阅\n     */\n    public static void subPrice(String symbol, boolean isSub) {\n        String str = \"35=V|55=\" + symbol + \"|263=\" + (isSub ? 1 : 2);\n        Log.d(TAG, \"subPrice: \" + str);\n        if (ForexWebSocket.getInstance().isConnctted) {\n            ForexWebSocket.getInstance().mWebSocket.send(str);\n        } else {\n            Log.e(TAG, \"subPrice: websocket未连接\");\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/api/WebSocketParser.java",
    "content": "package com.tophold.example.demo.kview.forex.api;\n\nimport android.util.Log;\n\nimport org.greenrobot.eventbus.EventBus;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport com.tophold.example.demo.kview.forex.model.WsPrice;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 21:26\n * 描 述 ：\n * ============================================================\n **/\npublic class WebSocketParser {\n    public static final String TAG = WebSocketParser.class.getSimpleName();\n\n    public static void fix2Object(String str) {\n        try {\n            if (str == null || str.length() == 0) return;\n            Log.d(TAG, \"fix2Object: \" + str);\n            String[] arrs = str.split(\"\\\\|\");\n            Map<String, String> map = new HashMap<>();\n            for (String arr : arrs) {\n                String[] items = arr.split(\"=\");\n                map.put(items[0], items[1]);\n            }\n            //maping\n            map2Obj(map);\n\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n    private static void map2Obj(Map<String, String> map) {\n\n        String type = map.get(\"35\");\n        if (type == null) {\n            Log.e(TAG, \"map2Obj: type == null\");\n            return;\n        }\n        if (type.equals(\"V\")) {\n            map2WsPrice(map);\n        }\n    }\n\n    private static void map2WsPrice(Map<String, String> map) {\n        WsPrice wsPrice = new WsPrice();\n        wsPrice.productName = map.get(\"55\");\n        wsPrice.lastUpdateTime = Long.parseLong(map.get(\"20068\"));\n        wsPrice.bidPrice = Double.parseDouble(map.get(\"132\"));\n        wsPrice.askPrice = Double.parseDouble(map.get(\"133\"));\n\n        EventBus.getDefault().post(wsPrice);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/api/XcfdService.java",
    "content": "package com.tophold.example.demo.kview.forex.api;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport io.reactivex.Observable;\nimport retrofit2.http.GET;\nimport retrofit2.http.Path;\nimport retrofit2.http.QueryMap;\nimport com.tophold.example.demo.kview.forex.model.XcfdQuotes;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 11:31\n * 描 述 ：\n * ============================================================\n **/\npublic interface XcfdService {\n    @GET(\"/kline/{productCode}/{type}\")\n    Observable<List<XcfdQuotes>> chartQuotes(@Path(\"productCode\") String productCode, @Path(\"type\") String type, @QueryMap Map<String, Object> params);\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/model/Forex.java",
    "content": "package com.tophold.example.demo.kview.forex.model;\n\nimport java.io.Serializable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 13:03\n * 描 述 ：\n * ============================================================\n **/\npublic class Forex implements Serializable{\n    public String id;\n    public String enName;\n    public String cnName;\n\n    public Forex(String id, String enName, String cnName) {\n        this.id=id;\n        this.enName=enName;\n        this.cnName=cnName;\n    }\n\n    @Override\n    public String toString() {\n        return \"Forex{\" +\n                \"id='\" + id + '\\'' +\n                \", enName='\" + enName + '\\'' +\n                \", cnName='\" + cnName + '\\'' +\n                '}';\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/model/WsPrice.java",
    "content": "package com.tophold.example.demo.kview.forex.model;\n\nimport com.google.gson.annotations.SerializedName;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/12/26 11:38\n * 描 述 ：\n * ============================================================\n **/\npublic class WsPrice  {\n\n    //TAG:55,COMMENT:产品\n    @SerializedName(\"55\")\n    public String productName;\n    //TAG:20068,COMMENT:系统最后价格时间\n    @SerializedName(\"20068\")\n    public long lastUpdateTime;\n    //TAG:132,COMMENT:--->对应老系统的卖价\n    @SerializedName(\"132\")\n    public double bidPrice;\n    //TAG:133,COMMENT:--->对应老系统的买价\n    @SerializedName(\"133\")\n    public double askPrice;\n\n    @Override\n    public String toString() {\n        return \"WsPrice{\" +\n                \", productName='\" + productName + '\\'' +\n                \", bidPrice='\" + bidPrice + '\\'' +\n                \", askPrice='\" + askPrice + '\\'' +\n                \"现价：\" + ((bidPrice + askPrice) / 2) +\n                '}';\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/model/XcfdQuotes.java",
    "content": "package com.tophold.example.demo.kview.forex.model;\n\nimport java.io.Serializable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 11:52\n * 描 述 ：\n * ============================================================\n **/\npublic class XcfdQuotes implements Serializable{\n    public String t; //201802080610\n    public String o;\n    public String h;\n    public String l;\n    public String c;\n\n    public long s;//数据开始时间\n    public long e;//结束时间\n\n    @Override\n    public String toString() {\n        return \"Quotes{\" +\n                \"t=\" + t +\n                \", o='\" + o + '\\'' +\n                \", h='\" + h + '\\'' +\n                \", l='\" + l + '\\'' +\n                \", c='\" + c + '\\'' +\n                \", s=\" + s +\n                \", e=\" + e +\n                '}';\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/ui/ForexActivity.java",
    "content": "package com.tophold.example.demo.kview.forex.ui;\n\nimport android.content.pm.ActivityInfo;\nimport android.os.Bundle;\nimport android.support.annotation.ColorRes;\nimport android.support.design.widget.TabLayout;\nimport android.support.v4.app.Fragment;\nimport android.view.View;\nimport android.view.Window;\nimport android.view.WindowManager;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.forex.api.WebSocketApi;\nimport com.tophold.example.demo.kview.forex.model.Forex;\nimport com.tophold.example.base.BaseActivity;\nimport com.tophold.example.utils.NoScrollViewPager;\nimport com.tophold.trade.utils.FormatUtil;\nimport com.tophold.trade.utils.TimeUtils;\nimport com.tophold.example.demo.kview.forex.ForexTab;\nimport com.tophold.trade.view.kview.Quotes;\n\npublic class ForexActivity extends BaseActivity {\n    public static final String KEY_FOREX = \"KEY_FOREX\";\n    public static final String KEY_HORIZONTAL = \"KEY_HORIZONTAL\";\n    private TabLayout mAfTlTablayout;\n    private NoScrollViewPager mAfVpViewpager;\n\n    private LinearLayout mAkvLlContainer;\n    private TextView mAkvTvH;\n    private TextView mAkvTvO;\n    private TextView mAkvTvTime;\n    private TextView mAkvTvL;\n    private TextView mAkvTvC;\n    private TextView mAkvTvP;\n    private TextView af_tv_symbol;\n    private TextView mAkvTvBlank;\n\n    //是否是横屏\n    boolean mIsHorizontal = false;\n\n    private List<ForexTab> mForexTabList;\n    private List<Fragment> mKViewFragmentList;\n\n    Forex mForex;\n\n    @Override\n    protected void getBundleExtras(Bundle extras) {\n        super.getBundleExtras(extras);\n        mForex = (Forex) extras.getSerializable(KEY_FOREX);\n        mIsHorizontal = extras.getBoolean(KEY_HORIZONTAL);\n    }\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        if (mIsHorizontal) {\n            requestWindowFeature(Window.FEATURE_NO_TITLE);// 隐藏标题\n            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,\n\n                    WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏\n        }\n        setContentView(R.layout.activity_forex);\n        initView();\n        initData();\n        initAdapter();\n        loadData();\n        initListener();\n    }\n\n    @Override\n    protected void onResume() {\n        if (mIsHorizontal) {\n            if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {\n                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);\n            }\n        }\n        super.onResume();\n    }\n\n    private void initView() {\n        mAfTlTablayout = (TabLayout) findViewById(R.id.af_tl_tablayout);\n        mAfVpViewpager = (NoScrollViewPager) findViewById(R.id.af_vp_viewpager);\n\n        mAkvLlContainer = (LinearLayout) findViewById(R.id.akv_ll_container);\n        mAkvTvH = (TextView) findViewById(R.id.akv_tv_h);\n        mAkvTvO = (TextView) findViewById(R.id.akv_tv_o);\n        mAkvTvTime = (TextView) findViewById(R.id.akv_tv_time);\n        mAkvTvL = (TextView) findViewById(R.id.akv_tv_l);\n        mAkvTvC = (TextView) findViewById(R.id.akv_tv_c);\n        mAkvTvP = (TextView) findViewById(R.id.akv_tv_p);\n        mAkvTvBlank = (TextView) findViewById(R.id.af_tv_blank);\n        af_tv_symbol = (TextView) findViewById(R.id.af_tv_symbol);\n\n        if (mIsHorizontal) {\n            af_tv_symbol.setVisibility(View.GONE);\n            mAkvTvBlank.setVisibility(View.GONE);\n        } else {\n            af_tv_symbol.setVisibility(View.VISIBLE);\n            mAkvTvBlank.setVisibility(View.VISIBLE);\n            af_tv_symbol.setText(mForex.cnName + \"(\" + mForex.enName + \")\");\n        }\n\n    }\n\n    private void initData() {\n        mForexTabList = new ArrayList<>();\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._timeShring, \"分时\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._1m, \"1分\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._5m, \"5分\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._15m, \"15分\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._30m, \"30分\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._1h, \"1时\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._4h, \"4时\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._1d, \"日K\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._1w, \"周K\"));\n        mForexTabList.add(new ForexTab(ForexTab.ForexType._1mon, \"月\"));\n\n        mAfTlTablayout.setTabMode(TabLayout.MODE_SCROLLABLE);\n\n        mKViewFragmentList = new ArrayList<>();\n        for (ForexTab forexTab : mForexTabList) {\n            mKViewFragmentList.add(KViewFragment.newInstance(forexTab, mForex));\n        }\n\n        //加载实时价格数据\n        WebSocketApi.subPrice(mForex.enName, true);\n    }\n\n    private void initAdapter() {\n        mAfVpViewpager.setAdapter(new KViewAdapter(getSupportFragmentManager(), mKViewFragmentList, mForexTabList));\n        mAfTlTablayout.setupWithViewPager(mAfVpViewpager);\n    }\n\n    private void loadData() {\n\n    }\n\n    private void initListener() {\n\n    }\n\n\n    public void hidenContainer() {\n        mAfTlTablayout.setVisibility(View.VISIBLE);\n        mAkvLlContainer.setVisibility(View.GONE);\n    }\n\n    public void showContanier(Quotes preQuotes, Quotes currentQuotes) {\n        mAfTlTablayout.setVisibility(View.GONE);\n        mAkvLlContainer.setVisibility(View.VISIBLE);\n        int digits = 5;\n        boolean isPositive;\n        String precent;\n        double dis = (currentQuotes.c - preQuotes.c) / currentQuotes.c * 100;\n        isPositive = dis >= 0;\n        precent = FormatUtil.formatBySubString(dis, 2);\n        precent += \"%\";\n\n        //\n        mAkvTvH.setText(FormatUtil.numFormat(currentQuotes.h, digits));\n        mAkvTvO.setText(FormatUtil.numFormat(currentQuotes.o, digits));\n        mAkvTvL.setText(FormatUtil.numFormat(currentQuotes.l, digits));\n        mAkvTvC.setText(FormatUtil.numFormat(currentQuotes.c, digits));\n        mAkvTvP.setText(precent);\n        mAkvTvTime.setText(TimeUtils.millis2String(currentQuotes.t, new SimpleDateFormat(\"MM-dd HH:mm\")));\n\n        if (isPositive) {\n            mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n            mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));\n        } else {\n            mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n            mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));\n        }\n    }\n\n    private int getMyColor(@ColorRes int colorId) {\n        return getResources().getColor(colorId);\n    }\n\n    public void showHorizontal(View view) {\n        Bundle bundle = new Bundle();\n        bundle.putBoolean(KEY_HORIZONTAL, true);\n        bundle.putSerializable(KEY_FOREX, mForex);\n        go(ForexActivity.class, bundle);\n    }\n\n    public boolean isHorizontal() {\n        return mIsHorizontal;\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        WebSocketApi.subPrice(mForex.enName, false);//取消订阅\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/ui/ForexListActivity.java",
    "content": "package com.tophold.example.demo.kview.forex.ui;\n\nimport android.os.Bundle;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\n\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.chad.library.adapter.base.BaseViewHolder;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.forex.model.Forex;\nimport com.tophold.example.base.BaseActivity;\n\npublic class ForexListActivity extends BaseActivity {\n    RecyclerView mAflRlListview;\n    BaseQuickAdapter<Forex, BaseViewHolder> mQuickAdapter;\n    List<Forex> mForexList;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_forex_list);\n        initView();\n        initData();\n        initAdapter();\n        loadData();\n        initListener();\n    }\n\n    private void initView() {\n        mAflRlListview = (RecyclerView) findViewById(R.id.afl_rl_listview);\n    }\n\n    private void initData() {\n        mForexList = new ArrayList<>();\n        mForexList.add(new Forex(\"1\", \"EURUSD\", \"欧元/美元\"));\n        mForexList.add(new Forex(\"2\", \"USDJPY\", \"美元/日元\"));\n        mForexList.add(new Forex(\"3\", \"AUDUSD\", \"澳元/美元\"));\n        mForexList.add(new Forex(\"4\", \"GBPUSD\", \"英镑/美元\"));\n        mForexList.add(new Forex(\"5\", \"USDCHF\", \"美元/瑞郎\"));\n        mForexList.add(new Forex(\"6\", \"USDSGD\", \"美元/新加坡元\"));\n        mForexList.add(new Forex(\"7\", \"USDCAD\", \"美元/加元\"));\n        mForexList.add(new Forex(\"8\", \"EURJPY\", \"欧元/日元\"));\n        mForexList.add(new Forex(\"9\", \"EURGBP\", \"欧元/英镑\"));\n        mForexList.add(new Forex(\"10\", \"NZDUSD\", \"纽元/美元\"));\n        mForexList.add(new Forex(\"11\", \"GBPJYP\", \"英镑/日元\"));\n        mForexList.add(new Forex(\"12\", \"USDMXN\", \"美元/墨西哥比索\"));\n        mForexList.add(new Forex(\"13\", \"GOLD\", \"黄金\"));\n        mForexList.add(new Forex(\"14\", \"SILVER\", \"白银\"));\n    }\n\n    private void initAdapter() {\n        mQuickAdapter = new BaseQuickAdapter<Forex, BaseViewHolder>(R.layout.item_activity_forex_list, mForexList) {\n            @Override\n            protected void convert(BaseViewHolder helper, Forex item) {\n                helper.setText(R.id.iafl_tv_enName, item.enName);\n                helper.setText(R.id.iafl_tv_znName, item.cnName);\n            }\n        };\n        mAflRlListview.setLayoutManager(new LinearLayoutManager(mContext));\n        mAflRlListview.setAdapter(mQuickAdapter);\n    }\n\n    private void loadData() {\n\n    }\n\n    private void initListener() {\n        mQuickAdapter.setOnItemClickListener((adapter, v, p) -> {\n            Forex forex = mForexList.get(p);\n            Bundle bundle = new Bundle();\n            bundle.putSerializable(ForexActivity.KEY_FOREX, forex);\n            go(ForexActivity.class, bundle);\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/ui/KViewAdapter.java",
    "content": "package com.tophold.example.demo.kview.forex.ui;\n\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentManager;\nimport android.support.v4.app.FragmentPagerAdapter;\n\nimport java.util.List;\n\nimport com.tophold.example.demo.kview.forex.ForexTab;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 14:38\n * 描 述 ：\n * ============================================================\n **/\npublic class KViewAdapter extends FragmentPagerAdapter {\n    private List<Fragment> mFragmentList;\n    List<ForexTab> mForexTabList;\n\n    public KViewAdapter(FragmentManager fm, List<Fragment> fragmentList, List<ForexTab> mForexTabList) {\n        super(fm);\n        this.mFragmentList = fragmentList;\n        this.mForexTabList = mForexTabList;\n    }\n\n\n    @Override\n    public Fragment getItem(int position) {\n        return mFragmentList.get(position);\n    }\n\n    @Override\n    public int getCount() {\n        return mFragmentList.size();\n    }\n\n    @Override\n    public CharSequence getPageTitle(int position) {\n        return mForexTabList.get(position).tabName;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/kview/forex/ui/KViewFragment.java",
    "content": "package com.tophold.example.demo.kview.forex.ui;\n\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Toast;\n\nimport org.greenrobot.eventbus.Subscribe;\nimport org.greenrobot.eventbus.ThreadMode;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport io.reactivex.Observer;\nimport io.reactivex.disposables.Disposable;\n\nimport com.tophold.example.base.BaseFragment;\nimport com.tophold.example.R;\nimport com.tophold.example.demo.kview.forex.api.RetrofitManager;\nimport com.tophold.example.demo.kview.forex.api.XcfdService;\nimport com.tophold.example.demo.kview.forex.model.Forex;\nimport com.tophold.example.demo.kview.forex.model.WsPrice;\nimport com.tophold.example.demo.kview.forex.model.XcfdQuotes;\nimport com.tophold.trade.utils.StringUtils;\nimport com.tophold.example.demo.kview.forex.ForexTab;\nimport com.tophold.trade.view.kview.KView;\nimport com.tophold.trade.view.kview.KViewListener;\nimport com.tophold.trade.view.kview.Quotes;\n\npublic class KViewFragment extends BaseFragment {\n    private static final String ARG_PARAM1 = \"param1\";\n    private static final String ARG_PARAM2 = \"param2\";\n    public static final int DEF_COUNT = 100;\n    private View mRootView;\n    private KView mFkKvKview;\n    ForexTab mForexTab;\n    Forex mForex;\n\n    //net\n    List<Quotes> mQuotesList;\n\n    public KViewFragment() {\n\n    }\n\n    public static KViewFragment newInstance(ForexTab mForexTab, Forex forex) {\n        KViewFragment fragment = new KViewFragment();\n        Bundle args = new Bundle();\n        args.putSerializable(ARG_PARAM1, mForexTab);\n        args.putSerializable(ARG_PARAM2, forex);\n        fragment.setArguments(args);\n        return fragment;\n    }\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        if (getArguments() != null) {\n            mForexTab = (ForexTab) getArguments().getSerializable(ARG_PARAM1);\n            mForex = (Forex) getArguments().getSerializable(ARG_PARAM2);\n        }\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        mRootView = inflater.inflate(R.layout.fragment_kview, container, false);\n        initView();\n        initData();\n        initAdapter();\n        loadData(null, false);\n        initListener();\n        return mRootView;\n    }\n\n    private void initView() {\n        mFkKvKview = (KView) mRootView.findViewById(R.id.fk_kv_kview);\n\n        mFkKvKview.setDigit(5);\n\n        if (mForexTab.mForexType == ForexTab.ForexType._timeShring) {\n            mFkKvKview.setShowTimSharing(true);\n        } else {\n            mFkKvKview.setShowTimSharing(false);\n        }\n\n        if (((ForexActivity) getActivity()).isHorizontal()) {\n            mFkKvKview.setShowMinor(true);\n        } else {\n            mFkKvKview.setShowMinor(false);\n        }\n    }\n\n    private void initData() {\n        mQuotesList = new ArrayList<>();\n    }\n\n    private void initAdapter() {\n\n    }\n\n    private void loadData(String start_time, final boolean isLoadMore) {\n        Map<String, Object> map = new HashMap<>();\n        map.put(\"count\", DEF_COUNT);\n        if (start_time != null) map.put(\"st\", start_time);\n        call(RetrofitManager.getInstance().create(XcfdService.class).chartQuotes(mForex.enName, mForexTab.getType(), map), new Observer<List<XcfdQuotes>>() {\n            @Override\n            public void onSubscribe(Disposable d) {\n\n            }\n\n            @Override\n            public void onNext(List<XcfdQuotes> xcfdQuotesList) {\n                if (StringUtils.isEmpty(xcfdQuotesList)) {\n                    Log.d(TAG, \"onNext: 数据为空\");\n                    return;\n                }\n                adapterData(xcfdQuotesList);\n\n                drawKView(isLoadMore);\n            }\n\n            @Override\n            public void onError(Throwable e) {\n                e.printStackTrace();\n                Toast.makeText(mContext, \"\" + e.getMessage(), Toast.LENGTH_SHORT).show();\n            }\n\n            @Override\n            public void onComplete() {\n\n            }\n        });\n    }\n\n    private void drawKView(boolean isLoadMore) {\n        if (!isLoadMore) {\n            mFkKvKview.setKViewData(mQuotesList, new KViewListener.MasterTouchListener() {\n                @Override\n                public void onLongTouch(Quotes preQuotes, Quotes currentQuotes) {\n                    ((ForexActivity) getActivity()).showContanier(preQuotes, currentQuotes);\n                }\n\n                @Override\n                public void onUnLongTouch() {\n                    ((ForexActivity) getActivity()).hidenContainer();\n                }\n\n                @Override\n                public void needLoadMore() {\n                    if (StringUtils.isEmpty(mQuotesList)) {\n                        mFkKvKview.loadMoreNoData();\n                        return;\n                    }\n                    Quotes quotes = mQuotesList.get(0);\n                    String showTime = quotes.getShowTime();\n                    loadData(showTime, true);\n                }\n            });\n        } else {\n            mFkKvKview.loadKViewData(mQuotesList);\n        }\n    }\n\n    private void adapterData(List<XcfdQuotes> xcfdQuotesList) {\n        List<Quotes> quotesList = new ArrayList<>();\n        for (XcfdQuotes xcfdQuotes : xcfdQuotesList) {\n            Quotes quotes = new Quotes(xcfdQuotes.o, xcfdQuotes.h, xcfdQuotes.l, xcfdQuotes.c, xcfdQuotes.s, xcfdQuotes.e);\n            quotesList.add(quotes);\n        }\n\n        mQuotesList.addAll(0, quotesList);//注意时序问题\n    }\n\n    private void initListener() {\n    }\n\n    @Override\n    public boolean isBindEventBusHere() {\n        return true;\n    }\n\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onRevicePrice(WsPrice wsPrice) {\n        if (wsPrice == null || !wsPrice.productName.equals(mForex.enName)) return;\n        double currPrice = (wsPrice.askPrice + wsPrice.bidPrice) / 2.0;//均价\n        String currPriceStr = String.valueOf(currPrice);\n\n        Quotes quotes = new Quotes(currPriceStr, currPriceStr, currPriceStr, currPriceStr, wsPrice.lastUpdateTime, wsPrice.lastUpdateTime);\n\n        mFkKvKview.pushKViewData(quotes, mForexTab.getTypeLength() * 1000);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/pie/PieChartActivity.kt",
    "content": "package com.tophold.example.demo.pie\n\nimport android.os.Bundle\nimport android.support.annotation.ColorInt\nimport android.support.v4.content.ContextCompat\nimport com.tophold.example.base.BaseActivity\nimport com.tophold.example.R\nimport com.tophold.trade.view.pie.PieEntrys\nimport kotlinx.android.synthetic.main.activity_pie_chart.*\n\nclass PieChartActivity : BaseActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_pie_chart)\n\n        initPieChart()\n\n        loadPieChart()\n    }\n\n    private fun loadPieChart() {\n        val pieEntrysList: MutableList<PieEntrys> = ArrayList()\n        pieEntrysList.add(PieEntrys(10f, \"80%\", getColorId(R.color.trade_analyze_pie_1), false, \"澳元/美元\"))\n        pieEntrysList.add(PieEntrys(50f, \"胜率 86.96%\", getColorId(R.color.trade_analyze_pie_2), true, \"英镑/美元\"))\n        pieEntrysList.add(PieEntrys(1f, \"60.71%\", getColorId(R.color.trade_analyze_pie_3), false, \"黄金\"))\n        pieEntrysList.add(PieEntrys(1f, \"76.47%\", getColorId(R.color.trade_analyze_pie_4), false, \"欧元/美元\"))\n\n        hatab_tapc_chart.pieEntryList = pieEntrysList\n    }\n\n    private fun initPieChart() {\n        hatab_tapc_chart.basePaddingTop = 40f\n        hatab_tapc_chart.basePaddingBottom = 40f\n    }\n\n    @ColorInt\n    private fun getColorId(colorId: Int): Int {\n        return ContextCompat.getColor(mContext,colorId)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/demo/seekbar/DoubleThumbSeekBarActivity.kt",
    "content": "package com.tophold.example.demo.seekbar\n\nimport android.os.Bundle\nimport android.support.annotation.NonNull\nimport com.tophold.example.base.BaseActivity\nimport com.tophold.example.R\nimport kotlinx.android.synthetic.main.activity_double_thumb_seek_bar.*\nimport com.tophold.trade.utils.RenderUtils.dp2px\nimport com.tophold.trade.view.seekbar.DoubleTumb\n\n\nclass DoubleThumbSeekBarActivity : BaseActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_double_thumb_seek_bar)\n        renderView1()\n    }\n\n    private fun renderView1() {\n        /**\n         * def\n         */\n        am_dtsv_seek0.init(loadTpSeekBar())\n\n        /**\n         * 加载单个thumb,从左边开始且最小值从最左边开始\n         */\n        am_dtsv_seek1.init(loadTpSeekBar(\n                false, -44.0, 66.0, true, 4,\n                true, false, 0.2, greenA = false))\n        /**\n         * 单个thumb,从右边开始且从左边开始最小值\n         */\n        am_dtsv_seek2.init(loadTpSeekBar(\n                false, -44.0, 66.0, true, 4,\n                false, true, 0.2, greenA = true))\n        /**\n         * 双thumb同向,最小值从左边开始\n         */\n        am_dtsv_seek3.init(loadTpSeekBar(\n                true, -44.0, 66.0, true, 4,\n                true, true, 0.2, false,\n                true, true, 0.33, false))\n        /**\n         * 双thumb同向,最小值从右边开始\n         */\n        am_dtsv_seek4.init(loadTpSeekBar(\n                true, -44.0, 66.0, false, 4,\n                false, true, 0.2, true,\n                false, true, 0.33, true))\n\n        /**\n         * 交叉方式显示\n         */\n        am_dtsv_seek5.init(loadTpSeekBar(\n                true, -44.0, 66.0, false, 4,\n                true, true, 0.2, false,\n                false, true, 0.33, true))\n    }\n\n    /**\n     * @param doubleThumb 是否启动双thumb\n     * @param min         最小值\n     * @param max         最大值\n     * @param minFromLeft 最小值是否从左边开始（注意和从哪边开始滑动无关）\n     * @param digit       格式化的小数位数\n     *\n     * @param fromLeftA   是否从左边开始滑动\n     * @param showTipsA   是否实时展示当前值\n     * @param progressA   默认进度（0~1）\n     * @param greenA      thumbA的背景色\n     *\n     * @param fromLeftB   是否从左边开始滑动\n     * @param showTipsB   是否实时展示当前值\n     * @param progressB   默认进度（0~1）\n     * @param greenB      thumbA的背景色\n     *\n     */\n    @NonNull\n    fun loadTpSeekBar(doubleThumb: Boolean = false, min: Double = 0.0, max: Double = 100.0, minFromLeft: Boolean = true, digit: Int = 2,\n                      fromLeftA: Boolean = true, showTipsA: Boolean = true, progressA: Double = 0.0, greenA: Boolean = false,\n                      fromLeftB: Boolean = true, showTipsB: Boolean = true, progressB: Double = 0.0, greenB: Boolean = false): DoubleTumb {\n\n        val thumbAForeground = if (!greenA) {\n            getCompatColor(R.color.dtsb_thumb1Color)\n        } else {\n            getCompatColor(R.color.dtsb_thumb2Color)\n\n        }\n\n        val thumbADrawable = if (!greenA) {\n            getCompatDrawable(R.drawable.layer_seekbar_thumb_red)\n        } else {\n            getCompatDrawable(R.drawable.layer_seekbar_thumb_green)\n        }\n\n        val thumbA = DoubleTumb.Thumb(thumbAForeground)\n        thumbA.progress = progressA//默认位置，百分比值（0~1）\n        thumbA.mFromLeft = fromLeftA//是否从左边开始滑动\n        thumbA.mShowTips = showTipsA\n        thumbA.setmThumb(thumbADrawable)\n        thumbA.setmThumbWidth(dp2px(mContext, 20f))\n        thumbA.setmThumbHight(dp2px(mContext, 25f))\n\n        var thumbB: DoubleTumb.Thumb? = null\n        //复杂模式显示两个thumb\n        if (doubleThumb) {\n            val thumbBForeground = if (!greenB) {\n                getCompatColor(R.color.dtsb_thumb11Color)\n            } else {\n                getCompatColor(R.color.dtsb_thumb22Color)\n\n            }\n            val thumbBDrawable = if (!greenB) {\n                getCompatDrawable(R.drawable.layer_seekbar_thumb_red)\n            } else {\n                getCompatDrawable(R.drawable.layer_seekbar_thumb_green)\n            }\n            thumbB = DoubleTumb.Thumb(thumbBForeground)\n            thumbB.progress = progressB\n            thumbB.mFromLeft = fromLeftB\n            thumbB.mShowTips = showTipsB\n            thumbB.setmThumb(thumbBDrawable)\n            thumbB.setmThumbWidth(dp2px(mContext, 20f))\n            thumbB.setmThumbHight(dp2px(mContext, 25f))\n        }\n\n        val doubleTumb = DoubleTumb(min, max,\n                dp2px(mContext, 4f).toFloat(),\n                getCompatColor(R.color.dtsb_bgColor),\n                thumbA,\n                thumbB)\n        //注意这里！！！\n        doubleTumb.mMinLeft = minFromLeft\n        doubleTumb.mDigit = digit\n        //根据总高度取设置\n        doubleTumb.mLineTop = dp2px(mContext, 40f)\n        doubleTumb.mLineBottom = dp2px(mContext, 10f)\n        doubleTumb.mLineLeft = dp2px(mContext, 8f)\n        doubleTumb.mLineRight = dp2px(mContext, 8f)\n\n        return doubleTumb\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/utils/GsonUtil.java",
    "content": "package com.tophold.example.utils;\n\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\nimport com.google.gson.reflect.TypeToken;\n\nimport java.lang.reflect.Type;\nimport java.util.Map;\n\n/**\n * <p>GSON工具类</p>\n *\n * @author\n * @version $Id: GsonUtil.java\n */\npublic class GsonUtil {\n\n    private static Gson gson = null;\n    private static Gson prettyGson = null;\n\n    static {\n        gson = new GsonBuilder()\n                .setDateFormat(\"yyyy-MM-dd HH:mm:ss\").create();\n        prettyGson = new GsonBuilder().setDateFormat(\"yyyy-MM-dd HH:mm:ss\")\n                .setPrettyPrinting()\n                .create();\n    }\n\n    /**\n     * 小写下划线的格式解析JSON字符串到对象\n     * <p>例如 is_success->isSuccess</p>\n     *\n     * @param json\n     * @param classOfT\n     * @return\n     */\n    public static <T> T fromJsonUnderScoreStyle(String json, Class<T> classOfT) {\n        return gson.fromJson(json, classOfT);\n    }\n\n    /**\n     * JSON字符串转为Map<String,String>\n     *\n     * @param json\n     * @return\n     */\n    @SuppressWarnings(\"all\")\n    public static <T> T fronJson2Map(String json) {\n        return gson.fromJson(json, new TypeToken<Map<String, String>>() {\n        }.getType());\n    }\n\n    /**\n     * 小写下划线的格式将对象转换成JSON字符串\n     *\n     * @param src\n     * @return\n     */\n    public static String toJson(Object src) {\n        return gson.toJson(src);\n    }\n\n    public static String toPrettyString(Object src) {\n        return prettyGson.toJson(src);\n    }\n\n    public static <T> T fromJson2Object(String src, Class<T> t) {\n        return gson.fromJson(src, t);\n    }\n\n    public static <T> T fromJson2Object(String src, Type typeOfT) {\n        return gson.fromJson(src, typeOfT);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/utils/NoScrollViewPager.java",
    "content": "package com.tophold.example.utils;\n\nimport android.content.Context;\nimport android.support.v4.view.ViewPager;\nimport android.util.AttributeSet;\nimport android.view.MotionEvent;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/22 14:55\n * 描 述 ：\n * ============================================================\n **/\npublic class NoScrollViewPager extends ViewPager {\n    public NoScrollViewPager(Context context) {\n        super(context);\n    }\n\n    public NoScrollViewPager(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    @Override\n    public boolean onTouchEvent(MotionEvent arg0) {\n        return false;\n    }\n\n    @Override\n    public boolean onInterceptTouchEvent(MotionEvent arg0) {\n        return false;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/tophold/example/utils/RxUtils.java",
    "content": "package com.tophold.example.utils;\n\nimport io.reactivex.FlowableTransformer;\nimport io.reactivex.Observable;\nimport io.reactivex.ObservableTransformer;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.schedulers.Schedulers;\n\n/**\n * Created by chao.qu at 2017/10/20\n *\n * @author quchao\n */\n\npublic class RxUtils {\n\n    /**\n     * 统一线程处理\n     *\n     * @param <T> 指定的泛型类型\n     * @return FlowableTransformer\n     */\n    public static <T> FlowableTransformer<T, T> rxFlSchedulerHelper() {\n        return flowable -> flowable.subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread());\n    }\n\n    /**\n     * 统一线程处理\n     *\n     * @param <T> 指定的泛型类型\n     * @return ObservableTransformer\n     */\n    public static <T> ObservableTransformer<T, T> rxSchedulerHelper() {\n        return observable -> observable.subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread());\n    }\n\n    /**\n     * 统一线程处理\n     *\n     * @param <T> 指定的泛型类型\n     * @return ObservableTransformer\n     */\n    public static <T> ObservableTransformer<T, T> rxApiSchedulerHelper() {\n        return observable -> observable.subscribeOn(Schedulers.io())\n                .unsubscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread());\n    }\n\n    /**\n     * 得到 Observable\n     *\n     * @param <T> 指定的泛型类型\n     * @return Observable\n     */\n    private static <T> Observable<T> createData(final T t) {\n        return Observable.create(emitter -> {\n            try {\n                emitter.onNext(t);\n                emitter.onComplete();\n            } catch (Exception e) {\n                emitter.onError(e);\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/drawable/layer_seekbar_thumb_green.xml",
    "content": "<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n    <item>\n        <shape>\n            <size\n                android:height=\"20dp\"\n                android:width=\"18dp\"/>\n            <solid android:color=\"@android:color/transparent\" />\n        </shape>\n    </item>\n    <item android:drawable=\"@drawable/ico_sl\"/>\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/layer_seekbar_thumb_red.xml",
    "content": "<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n    <item>\n        <shape>\n            <size\n                android:height=\"20dp\"\n                android:width=\"18dp\"/>\n            <solid android:color=\"@android:color/transparent\" />\n        </shape>\n    </item>\n    <item android:drawable=\"@drawable/ico_tp\"/>\n</layer-list>"
  },
  {
    "path": "app/src/main/res/layout/activity_double_thumb_seek_bar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\">\n\n        <com.tophold.trade.view.seekbar.DoubleThumbSeekBar\n            android:id=\"@+id/am_dtsv_seek0\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"54dp\"\n            android:layout_marginLeft=\"4dp\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginRight=\"4dp\"\n            android:background=\"#fff\" />\n\n        <com.tophold.trade.view.seekbar.DoubleThumbSeekBar\n            android:id=\"@+id/am_dtsv_seek1\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"54dp\"\n            android:layout_marginLeft=\"4dp\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginRight=\"4dp\"\n            android:background=\"#fff\" />\n\n\n        <com.tophold.trade.view.seekbar.DoubleThumbSeekBar\n            android:id=\"@+id/am_dtsv_seek2\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"54dp\"\n            android:layout_marginLeft=\"4dp\"\n            android:layout_marginTop=\"20dp\"\n            android:layout_marginRight=\"4dp\"\n            android:background=\"#fff\" />\n\n        <com.tophold.trade.view.seekbar.DoubleThumbSeekBar\n            android:id=\"@+id/am_dtsv_seek3\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"54dp\"\n            android:layout_marginLeft=\"4dp\"\n            android:layout_marginTop=\"20dp\"\n            android:layout_marginRight=\"4dp\"\n            android:background=\"#fff\" />\n\n        <com.tophold.trade.view.seekbar.DoubleThumbSeekBar\n            android:id=\"@+id/am_dtsv_seek4\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"54dp\"\n            android:layout_marginLeft=\"4dp\"\n            android:layout_marginTop=\"20dp\"\n            android:layout_marginRight=\"4dp\"\n            android:background=\"#fff\" />\n\n        <com.tophold.trade.view.seekbar.DoubleThumbSeekBar\n            android:id=\"@+id/am_dtsv_seek5\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"54dp\"\n            android:layout_marginLeft=\"4dp\"\n            android:layout_marginTop=\"20dp\"\n            android:layout_marginRight=\"4dp\"\n            android:background=\"#fff\" />\n    </LinearLayout>\n\n</ScrollView>\n\n"
  },
  {
    "path": "app/src/main/res/layout/activity_forex.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"40dp\"\n        android:orientation=\"vertical\">\n\n        <android.support.design.widget.TabLayout\n            android:id=\"@+id/af_tl_tablayout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"40dp\"\n            app:tabIndicatorColor=\"@color/color_tb_indicator\"\n            app:tabSelectedTextColor=\"@color/color_tb_selectedTxt\"\n            app:tabTextColor=\"@color/color_tb_Txt\"\n            />\n\n        <!--按下的指标显示-->\n        <LinearLayout\n            android:id=\"@+id/akv_ll_container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"40dp\"\n            android:background=\"#e7e3e3\"\n            android:orientation=\"vertical\"\n            android:paddingTop=\"4dp\"\n            android:visibility=\"gone\">\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"20dp\"\n                android:orientation=\"horizontal\">\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"高:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_h\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"开:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_o\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_time\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"20dp\"\n                android:orientation=\"horizontal\">\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"低:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_l\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"收:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_c\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"幅:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_p\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n\n            </LinearLayout>\n        </LinearLayout>\n    </LinearLayout>\n\n\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"0.5dp\"\n        android:background=\"#8f8d8d\"/>\n\n    <com.tophold.example.utils.NoScrollViewPager\n        android:id=\"@+id/af_vp_viewpager\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"300dp\"/>\n\n    <TextView\n        android:id=\"@+id/af_tv_symbol\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"40dp\"\n        android:text=\"欧元/美元(USDCAD)\"\n        android:gravity=\"center\"\n        android:background=\"#a7a4a4\"/>\n    <TextView\n        android:id=\"@+id/af_tv_blank\"\n        android:onClick=\"showHorizontal\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_marginTop=\"4dp\"\n        android:background=\"#cccccc\"\n        android:gravity=\"center\"\n        android:text=\"业务模块(单击这里进入横屏)\"/>\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_forex_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/afl_rl_listview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"/>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_fund.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:gravity=\"center\"\n    android:orientation=\"vertical\"\n    android:background=\"#000\"\n\n    >\n    <com.tophold.trade.view.fund.FundView\n        android:id=\"@+id/af_fv_fundview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"300dp\"\n        android:background=\"#fff\"/>\n</LinearLayout>  "
  },
  {
    "path": "app/src/main/res/layout/activity_huobi.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"40dp\"\n        android:orientation=\"vertical\">\n\n        <android.support.design.widget.TabLayout\n            android:id=\"@+id/af_tl_tablayout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"40dp\"\n            app:tabIndicatorColor=\"@color/color_tb_indicator\"\n            app:tabSelectedTextColor=\"@color/color_tb_selectedTxt\"\n            app:tabTextColor=\"@color/color_tb_Txt\"\n            />\n\n        <!--按下的指标显示-->\n        <LinearLayout\n            android:id=\"@+id/akv_ll_container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"40dp\"\n            android:background=\"#e7e3e3\"\n            android:orientation=\"vertical\"\n            android:paddingTop=\"4dp\"\n            android:visibility=\"gone\">\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"20dp\"\n                android:orientation=\"horizontal\">\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"高:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_h\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"开:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_o\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_time\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"20dp\"\n                android:orientation=\"horizontal\">\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"低:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_l\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"收:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_c\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n                <LinearLayout\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_weight=\"1\"\n                    android:gravity=\"center\">\n\n                    <TextView\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"幅:\"\n                        android:textColor=\"#000\"\n                        android:textSize=\"12dp\"/>\n\n                    <TextView\n                        android:id=\"@+id/akv_tv_p\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:text=\"@string/string_placeHold\"\n                        android:textColor=\"#f00\"\n                        android:textSize=\"12dp\"/>\n                </LinearLayout>\n\n\n            </LinearLayout>\n        </LinearLayout>\n    </LinearLayout>\n\n\n    <View\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"0.5dp\"\n        android:background=\"#8f8d8d\"/>\n\n    <com.tophold.example.utils.NoScrollViewPager\n        android:id=\"@+id/af_vp_viewpager\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"300dp\"/>\n\n    <TextView\n        android:id=\"@+id/af_tv_symbol\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"40dp\"\n        android:text=\"欧元/美元(USDCAD)\"\n        android:gravity=\"center\"\n        android:background=\"#a7a4a4\"/>\n    <TextView\n        android:id=\"@+id/af_tv_blank\"\n        android:onClick=\"showHorizontal\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_marginTop=\"4dp\"\n        android:background=\"#cccccc\"\n        android:gravity=\"center\"\n        android:text=\"业务模块(单击这里进入横屏)\"/>\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_huobi_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    android:background=\"#d9cfcf\">\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/afl_rl_listview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"/>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_kview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\">\n\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:onClick=\"kViewVertical\"\n        android:text=\"K线图竖屏（本地数据）\" />\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:onClick=\"kViewHorizontal\"\n        android:text=\"K线图横屏（本地数据）\" />\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:onClick=\"kViewEvaluation\"\n        android:text=\"外汇Demo(可能因为API限制显示不了)\"\n        android:textAllCaps=\"false\" />\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:onClick=\"btnDemo\"\n        android:text=\"数字货币demo(火币API)\"\n        android:textAllCaps=\"false\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_kview_horizontal.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <!--按下的指标显示-->\n    <LinearLayout\n        android:id=\"@+id/akv_ll_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"#e7e3e3\"\n        android:orientation=\"vertical\"\n        android:paddingTop=\"4dp\"\n        android:visibility=\"invisible\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"20dp\"\n            android:orientation=\"horizontal\">\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"高:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_h\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"开:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_o\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:id=\"@+id/akv_tv_time\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n\n        </LinearLayout>\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"20dp\"\n            android:orientation=\"horizontal\">\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"低:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_l\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"收:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_c\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"幅:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_p\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n\n        </LinearLayout>\n    </LinearLayout>\n\n    <com.tophold.trade.view.kview.KView\n        android:id=\"@+id/akv_kv_kview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"0dp\"\n        android:layout_weight=\"1\"/>\n\n    <Button\n        android:onClick=\"showCandle\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"30dp\"\n        android:text=\"点击展示蜡烛图\"/>\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_kview_vertical.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <!--按下的指标显示-->\n    <LinearLayout\n        android:id=\"@+id/akv_ll_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"50dp\"\n        android:layout_marginTop=\"20dp\"\n        android:background=\"#e7e3e3\"\n        android:orientation=\"vertical\"\n        android:paddingTop=\"4dp\"\n        android:visibility=\"invisible\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"25dp\"\n            android:orientation=\"horizontal\">\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"高:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_h\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"开:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_o\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:id=\"@+id/akv_tv_time\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n\n        </LinearLayout>\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"25dp\"\n            android:orientation=\"horizontal\">\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"低:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_l\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"收:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_c\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n            <LinearLayout\n                android:layout_width=\"0dp\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:gravity=\"center\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"幅:\"\n                    android:textColor=\"#000\"\n                    android:textSize=\"12dp\"/>\n\n                <TextView\n                    android:id=\"@+id/akv_tv_p\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:text=\"@string/string_placeHold\"\n                    android:textColor=\"#f00\"\n                    android:textSize=\"12dp\"/>\n            </LinearLayout>\n\n\n        </LinearLayout>\n    </LinearLayout>\n\n    <com.tophold.trade.view.kview.KView\n        android:id=\"@+id/akv_kv_kview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"300dp\"/>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"45dp\"\n        android:layout_marginTop=\"100dp\"\n        android:orientation=\"horizontal\">\n\n        <Button\n            android:id=\"@+id/akv_btn_showCandle\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"45dp\"\n            android:layout_weight=\"1\"\n            android:onClick=\"showCandle\"\n            android:text=\"点击展示蜡烛图\"/>\n\n        <View\n            android:layout_width=\"10dp\"\n            android:layout_height=\"match_parent\"/>\n\n        <Button\n            android:id=\"@+id/akv_btn_showMinnor\"\n            android:layout_width=\"0dp\"\n            android:layout_height=\"45dp\"\n            android:layout_weight=\"1\"\n            android:onClick=\"showMinor\"\n            android:text=\"点击不显示副图\"/>\n    </LinearLayout>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"vertical\">\n\n    <TextView\n        android:id=\"@+id/version\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"top\"\n        android:gravity=\"center\"\n        android:padding=\"16dp\"\n        android:text=\"verisonName:1.4,versionCode(git head):\"/>\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"100dp\"\n        android:onClick=\"fundView\"\n        android:text=\"去看自定义基金View Demo\"\n        android:textAllCaps=\"false\"\n        />\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:textAllCaps=\"false\"\n        android:onClick=\"kViewDemo\"\n        android:text=\"去看KView Demo\"\n        />\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:onClick=\"onPieTest\"\n        android:text=\"去看PieChart饼图 Demo\"\n        android:textAllCaps=\"false\"\n        />\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:onClick=\"onSeekBarTest\"\n        android:text=\"去看DoubleThumbSeekBar Demo\"\n        android:textAllCaps=\"false\" />\n\n    <Button\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:onClick=\"onRx\"\n        android:text=\"去看Rx\"\n        android:textAllCaps=\"false\" />\n\n</LinearLayout>  "
  },
  {
    "path": "app/src/main/res/layout/activity_pie_chart.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#dedbdb\"\n    android:gravity=\"center\">\n\n\n    <com.tophold.trade.view.pie.PieChartView\n        android:id=\"@+id/hatab_tapc_chart\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"215dp\"\n        android:background=\"#fff\"/>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_huobi.xml",
    "content": "<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n             android:layout_width=\"match_parent\"\n             android:layout_height=\"match_parent\">\n\n    <com.tophold.trade.view.kview.KView\n        android:id=\"@+id/fk_kv_kview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"/>\n</FrameLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_kview.xml",
    "content": "<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n             android:layout_width=\"match_parent\"\n             android:layout_height=\"match_parent\">\n\n    <com.tophold.trade.view.kview.KView\n        android:id=\"@+id/fk_kv_kview\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"/>\n</FrameLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/item_activity_forex_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"45dp\"\n    android:background=\"#d9cfcf\">\n\n    <TextView\n        android:id=\"@+id/iafl_tv_znName\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginLeft=\"10dp\"\n        android:layout_marginTop=\"4dp\"\n        android:gravity=\"center_vertical\"\n        android:text=\"黄金\"/>\n\n    <TextView\n        android:id=\"@+id/iafl_tv_enName\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@+id/iafl_tv_znName\"\n        android:layout_marginLeft=\"10dp\"\n        android:gravity=\"center_vertical\"\n        android:text=\"GOLD\"/>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"1dp\"\n        android:layout_alignParentBottom=\"true\"\n        android:background=\"#ffffff\"/>\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/item_activity_huobi_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"45dp\"\n    android:background=\"#fff\">\n\n    <TextView\n        android:id=\"@+id/iafl_tv_znName\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginLeft=\"10dp\"\n        android:layout_marginTop=\"4dp\"\n        android:gravity=\"center_vertical\"\n        android:textSize=\"18sp\"\n        android:text=\"黄金\"/>\n\n    <TextView\n        android:id=\"@+id/iafl_tv_enName\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@+id/iafl_tv_znName\"\n        android:layout_marginLeft=\"10dp\"\n        android:textSize=\"10sp\"\n        android:gravity=\"center_vertical\"\n        android:text=\"GOLD\"/>\n\n    <TextView\n        android:id=\"@+id/iafl_tv_part\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:layout_centerInParent=\"true\"\n        android:layout_marginRight=\"10dp\"\n        android:text=\"主区\"/>\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"1dp\"\n        android:layout_alignParentBottom=\"true\"\n        android:background=\"#8b8989\"/>\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n\n    <!--具体业务-->\n    <color name=\"color_tb_indicator\">#ef1e13</color>\n    <color name=\"color_tb_selectedTxt\">#ef1e13</color>\n    <color name=\"color_tb_Txt\">#8a8a8b</color>\n\n    <!--交易分析四个颜色-->\n    <color name=\"trade_analyze_pie_1\">#f5b5ff</color>\n    <color name=\"trade_analyze_pie_2\">#aaacff</color>\n    <color name=\"trade_analyze_pie_3\">#96e0ff</color>\n    <color name=\"trade_analyze_pie_4\">#ffcf97</color>\n\n    <!--seekbar-->\n    <color name=\"dtsb_bgColor\">#cecfce</color>\n    <color name=\"dtsb_thumb1Color\">#ed5f53</color>\n    <color name=\"dtsb_thumb11Color\">#f59e97</color>\n    <color name=\"dtsb_thumb2Color\">#63a65e</color>\n    <color name=\"dtsb_thumb22Color\">#9cfa95</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">FinancialCustomerView</string>\n    <string name=\"string_placeHold\">--</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.DayNight.NoActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n    <style name=\"AppTheme_Fullscreen\" parent=\"Theme.AppCompat.DayNight.NoActionBar\">\n\n        <item name=\"android:windowNoTitle\">true</item>\n        <item name=\"android:windowFullscreen\">true</item>\n        <item name=\"android:windowIsTranslucent\">true</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "app/src/test/java/wgyscsf/financialcustomerview/ExampleUnitTest.java",
    "content": "package com.tophold.example;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript { \n    ext.kotlin_version = '1.3.41'\n\n    repositories {\n        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }\n        google()\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.5.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n        //classpath 'com.novoda:bintray-release:0.5.0'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\" }\n}\n\nallprojects {\n    repositories {\n        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }\n        google()\n        jcenter()\n        maven { url \"https://jitpack.io\" }\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "financiallib/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "financiallib/build.gradle",
    "content": "apply plugin: 'com.android.library'\n//apply plugin: 'com.novoda.bintray-release'\n\nandroid {\n    compileSdkVersion 28\n\n    defaultConfig {\n        minSdkVersion 14\n        versionCode 2\n        versionName \"0.0.2\"\n\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n\n    }\n\n    buildTypes {\n        debug {\n\n        }\n        beta {\n\n        }\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n\n    }\n    lintOptions {\n        abortOnError false\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\n\ndependencies {\n    implementation 'com.android.support:appcompat-v7:28.0.0'\n    api 'com.google.code.gson:gson:2.8.5'\n}\n\n\n\n//        ./gradlew clean build bintrayUpload\n// -PbintrayUser=wgyscsf\n// -PbintrayKey=xxxxxxxxxxxxxxxxxxxxxx\n// -PdryRun=false\n\n//添加\n//publish {\n//    repoName ='maven'//和在Bintray网站创建的仓库名对应\n//    userOrg = 'wgyscsf'//bintray.com用户名\n//    groupId = 'com.wgyscsf'//jcenter上的路径\n//    artifactId = 'financialLib'//项目名称\n//    publishVersion = '0.0.2'//版本号\n//    desc = 'this is the first version'//描述，不重要\n//    website = 'https://github.com/scsfwgy/FinancialCustomerView'//网站，不重要；尽量模拟github上的地址，例如我这样的；当然你有地址最好了\n//}"
  },
  {
    "path": "financiallib/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "financiallib/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"com.tophold.trade\"/>\n"
  },
  {
    "path": "financiallib/src/main/java/TODO.md",
    "content": "#### TODO\n1. 对于默认值不显示的指标，比如ma,假如算出来的本身就和默认值一样就会导致\"误判\".\n2. 首页的ma边界判断应该有问题，参考vol ma"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/Constant.java",
    "content": "package com.tophold.trade;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/05/19 16:28\n * 描 述 ：\n * ============================================================\n */\npublic class Constant {\n    public static final String ESPECIAL_TAG=\"ESPECIAL_TAG\";\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/utils/FormatUtil.java",
    "content": "package com.tophold.trade.utils;\n\nimport android.util.Log;\n\nimport java.math.BigDecimal;\nimport java.util.Locale;\n\n\npublic class FormatUtil {\n\n    /**\n     * 浮点数格式化\n     *\n     * @param isPercentage 是否为分数\n     * @param needSign     是否需要正号\n     * @param isMoney      是否使用金钱格式(每3位用\",\"分隔)\n     * @param digit        需要保留的位数\n     * @param num          需要格式化的值(int、float、double、String、byte均可)\n     */\n    public static String format(boolean isPercentage, boolean needSign, boolean isMoney, int digit, Object num) {\n        digit = digit < 0 ? 0 : digit;\n        if (num == null) num = 0;\n\n        double converted;//需求大多四舍五入  float保留位数会舍去后面的\n        try {\n            converted = Double.parseDouble(num.toString());\n        } catch (Throwable e) {\n            Log.e(\"FormatErr\", \"Input number is not kind number\");\n            converted = 0d;\n        }\n        StringBuilder sb = new StringBuilder(\"%\");\n\n        if (needSign && (converted > 0)) {\n            sb.append(\"+\");\n        }\n\n        if (isMoney) {\n            sb.append(\",\");\n        }\n\n        sb.append(\".\").append(digit).append(\"f\");\n\n        if (isPercentage) {\n            sb.append(\"%%\");\n        }\n\n        return String.format(Locale.getDefault(), sb.toString(), converted);\n    }\n\n    public static String numFormat(Object num, int digit) {\n        return numFormat(false, digit, num);\n    }\n\n    public static String numFormat(boolean needSign, int digit, Object num) {\n        return format(false, needSign, false, digit, num);\n    }\n\n    /**\n     * 带%格式化\n     */\n    public static String percentageFormat(Object num) {\n        return percentageFormat(true, num);\n    }\n\n    public static String percentageFormat(boolean needSign, Object num) {\n        return percentageFormat(needSign, 2, num);\n    }\n\n    public static String percentageFormat(int digit, Object num) {\n        return percentageFormat(false, digit, num);\n    }\n\n    public static String percentageFormat(boolean needSign, int digit, Object num) {\n        return format(true, needSign, false, digit, num);\n    }\n\n    /**\n     * 以金钱格式表示的数字\n     */\n    public static String moneyFormat(Object num) {\n        return moneyFormat(true, num);\n    }\n\n    public static String moneyFormat(boolean isPercentage, Object num) {\n        return moneyFormat(isPercentage, 2, num);\n    }\n\n    public static String moneyFormat(boolean isPercentage, int digit, Object num) {\n        return format(isPercentage, false, true, digit, num);\n    }\n\n    public static String stringAppend(Object object) {\n        if (object != null)\n            return String.format(Locale.getDefault(), \"%s\", object);\n        else\n            return \"- -\";\n    }\n\n    /**\n     * 不四舍五入取n位小数\n     */\n    public static String formatBySubString(Object obj, int digit) {\n        if (obj == null) return \"0\";\n        String num = String.valueOf(obj);\n        digit = digit < 0 ? 0 : digit;\n        int i = num.indexOf(\".\");\n        if (i >= 0) {\n            if (num.length() - ++i > digit) {\n                num = num.substring(0, i + digit);\n            }\n        }\n        return num;\n    }\n\n    /**\n     * 进位处理\n     *\n     * @param scale 保留几位\n     */\n    public static String roundUp(int scale, Object num) {\n        BigDecimal decimal = new BigDecimal(num.toString());\n        return decimal.setScale(scale, BigDecimal.ROUND_UP).toString();\n    }\n\n    /**\n     * 直接舍弃多余小数\n     */\n    public static String roundDown(int scale, Object num) {\n        BigDecimal decimal = new BigDecimal(num.toString());\n        return decimal.setScale(scale, BigDecimal.ROUND_DOWN).toString();\n    }\n\n    public static void main(String args[]) {\n        double num1 = -123456.789000;\n        double num2 = 0;\n        double num3 = 1.00;\n        double num4 = 1444444444;\n        double num5 = 123.123;\n        double num6 = 123.123;\n        double num7 = 123.123;\n        double num8 = 123.123;\n        double num9 = 123.123;\n        double num10 = 123.123;\n        String numStr1 = format(false, false, false, 5, num1);\n        String numStr2 = format(true, false, false, 5, num1);\n        String numStr3 = format(false, true, false, 5, num1);\n        String numStr4 = format(false, false, true, 5, num1);\n        System.out.println(numStr1);\n        System.out.println(numStr2);\n        System.out.println(numStr3);\n        System.out.println(numStr4);\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/utils/GsonUtil.java",
    "content": "package com.tophold.trade.utils;\n\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\nimport com.google.gson.reflect.TypeToken;\n\nimport java.lang.reflect.Type;\nimport java.util.Map;\n\n/**\n * <p>GSON工具类</p>\n *\n * @author\n * @version $Id: GsonUtil.java\n */\npublic class GsonUtil {\n\n    private static Gson gson = null;\n    private static Gson prettyGson = null;\n\n    static {\n        gson = new GsonBuilder()\n                .setDateFormat(\"yyyy-MM-dd HH:mm:ss\").create();\n        prettyGson = new GsonBuilder().setDateFormat(\"yyyy-MM-dd HH:mm:ss\")\n                .setPrettyPrinting()\n                .create();\n    }\n\n    /**\n     * 小写下划线的格式解析JSON字符串到对象\n     * <p>例如 is_success->isSuccess</p>\n     *\n     * @param json\n     * @param classOfT\n     * @return\n     */\n    public static <T> T fromJsonUnderScoreStyle(String json, Class<T> classOfT) {\n        return gson.fromJson(json, classOfT);\n    }\n\n    /**\n     * JSON字符串转为Map<String,String>\n     *\n     * @param json\n     * @return\n     */\n    @SuppressWarnings(\"all\")\n    public static <T> T fronJson2Map(String json) {\n        return gson.fromJson(json, new TypeToken<Map<String, String>>() {\n        }.getType());\n    }\n\n    /**\n     * 小写下划线的格式将对象转换成JSON字符串\n     *\n     * @param src\n     * @return\n     */\n    public static String toJson(Object src) {\n        return gson.toJson(src);\n    }\n\n    public static String toPrettyString(Object src) {\n        return prettyGson.toJson(src);\n    }\n\n    public static <T> T fromJson2Object(String src, Class<T> t) {\n        return gson.fromJson(src, t);\n    }\n\n    public static <T> T fromJson2Object(String src, Type typeOfT) {\n        return gson.fromJson(src, typeOfT);\n    }\n\n    public static Gson getGson() {\n        return gson;\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/utils/RegxUtils.java",
    "content": "package com.tophold.trade.utils;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/10/25 16:08\n * 描 述 ：\n * ============================================================\n **/\npublic class RegxUtils {\n    public static float getPureDouble(String str) {\n        if (str == null || str.length() == 0) return 0;\n        float result = 0;\n        try {\n            Pattern compile = Pattern.compile(\"(\\\\d+\\\\.\\\\d+)|(\\\\d+)\");//如何提取带负数d ???\n            Matcher matcher = compile.matcher(str);\n            matcher.find();\n            String string = matcher.group();//提取匹配到的结果\n            result = Float.parseFloat(string);\n        } catch (NumberFormatException e) {\n            e.printStackTrace();\n        }\n        return result;\n    }\n\n    public static void main(String[] args){\n\n        test();\n    }\n    public static void test(){\n        System.out.println(getPureDouble(\"12\"));\n        System.out.println(getPureDouble(\"wew3423.36\"));\n        System.out.println(getPureDouble(\"wewsf\"));\n        System.out.println(getPureDouble(\"000\"));\n        System.out.println(getPureDouble(null));\n    }\n\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/utils/RenderUtils.java",
    "content": "package com.tophold.trade.utils;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.graphics.Canvas;\nimport android.graphics.Matrix;\nimport android.graphics.NinePatch;\nimport android.graphics.Rect;\nimport android.graphics.drawable.BitmapDrawable;\nimport android.graphics.drawable.Drawable;\n\n/**\n * ================================================\n * 作    者：JayGoo\n * 版    本：\n * 创建日期：2018/5/8\n * 描    述:\n * ================================================\n */\npublic class RenderUtils {\n\n    /**\n     *  make a drawable to a bitmap\n     * @param drawable drawable you want convert\n     * @return converted bitmap\n     */\n    public static Bitmap drawableToBitmap(int size, Drawable drawable) {\n        Bitmap bitmap = null;\n        if (drawable instanceof BitmapDrawable) {\n            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;\n            bitmap = bitmapDrawable.getBitmap();\n            if (bitmap != null && bitmap.getHeight() > 0) {\n                Matrix matrix = new Matrix();\n                float scaleHeight = size * 1.0f / bitmapDrawable.getIntrinsicHeight();\n                matrix.postScale(scaleHeight, scaleHeight);\n                bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);\n                return bitmap;\n            }\n        }\n        bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);\n        Canvas canvas = new Canvas(bitmap);\n        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());\n        drawable.draw(canvas);\n        return bitmap;\n    }\n\n    /**\n     * make a drawable to a bitmap\n     *\n     * @param drawable drawable you want convert\n     * @return converted bitmap\n     */\n    public static Bitmap drawableToBitmap(Drawable drawable) {\n        return drawableToBitmap(drawable, 0, 0);\n    }\n\n    /**\n     * make a drawable to a bitmap\n     *\n     * @param drawable drawable you want convert\n     * @return converted bitmap\n     */\n    public static Bitmap drawableToBitmap(Drawable drawable, float width, float hight) {\n        Bitmap bitmap = null;\n        float scaleWidth = width > 0 ? width : drawable.getIntrinsicWidth();\n        float scaleHeight = hight > 0 ? hight : drawable.getIntrinsicHeight();\n        if (drawable instanceof BitmapDrawable) {\n            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;\n            bitmap = bitmapDrawable.getBitmap();\n            if (bitmap != null && bitmap.getHeight() > 0) {\n                Matrix matrix = new Matrix();\n                matrix.postScale(scaleWidth, scaleHeight);\n                bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);\n                return bitmap;\n            }\n        }\n        bitmap = Bitmap.createBitmap((int) scaleWidth, (int) scaleHeight, Bitmap.Config.ARGB_4444);\n        Canvas canvas = new Canvas(bitmap);\n        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());\n        drawable.draw(canvas);\n        return bitmap;\n    }\n    /**\n     * draw 9Path\n     *\n     * @param canvas Canvas\n     * @param bmp 9path bitmap\n     * @param rect 9path rect\n     */\n    public static void drawNinePath(Canvas canvas, Bitmap bmp, Rect rect) {\n        NinePatch patch = new NinePatch(bmp, bmp.getNinePatchChunk(), null);\n        patch.draw(canvas, rect);\n    }\n\n    public static int dp2px(Context context, float dpValue) {\n        if (context == null || compareFloat(0f,dpValue) == 0)return 0;\n        final float scale = context.getResources().getDisplayMetrics().density;\n        return (int) (dpValue * scale + 0.5f);\n    }\n\n\n    /**\n     * Compare the size of two floating point numbers\n     * @param a\n     * @param b\n     * @return 1 is a > b\n     * -1 is a < b\n     * 0 is a == b\n     */\n    public static int compareFloat(float a, float b) {\n        int ta = Math.round(a * 100000);\n        int tb = Math.round(b * 100000);\n        if (ta > tb) {\n            return 1;\n        } else if (ta < tb) {\n            return -1;\n        } else {\n            return 0;\n        }\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/utils/ScreenUtils.java",
    "content": "package com.tophold.trade.utils;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.graphics.Rect;\nimport android.graphics.RectF;\nimport android.os.Build;\nimport android.util.DisplayMetrics;\nimport android.view.Display;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.WindowManager;\n\n\nimport java.lang.reflect.Method;\n\n/**\n * 获取屏幕宽高等 相关工具类\n */\n@SuppressWarnings(\"WeakerAccess\")\npublic class ScreenUtils {\n    public static int screenWidth;\n    public static int screenHeight;\n    public static float density;\n    public static float scaledDensity;\n    public static int statusbarheight;\n    public static int navbarheight;\n    public static int realScreenHeight;\n    public static int realScreenWidth;\n\n    static {\n        init();\n    }\n\n    private static void init() {\n        DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();\n        screenWidth = displayMetrics.widthPixels;\n        screenHeight = displayMetrics.heightPixels;\n        density = displayMetrics.density;\n        scaledDensity = displayMetrics.scaledDensity;\n    }\n\n    /**\n     * 获取屏幕宽度\n     */\n    public static int getScreenWidth() {\n        return screenWidth;\n    }\n\n    /**\n     * 获取屏幕高度(不包含底部虚拟按键)\n     */\n    public static int getScreenHeight() {\n        return screenHeight;\n    }\n\n    public static int px2dip(float pxValue) {\n        return (int) (pxValue / density + 0.5f);\n    }\n\n    public static int dip2px(float dpValue) {\n        return (int) (dpValue * density + 0.5f);\n    }\n\n    /**\n     * 将px值转换为sp值，保证文字大小不变\n     */\n    public static float px2sp(float pxValue) {\n        return pxValue / scaledDensity;\n    }\n\n    /**\n     * 将sp值转换为px值，保证文字大小不变\n     */\n    public static float sp2px(float spValue) {\n        return spValue * scaledDensity;\n    }\n\n    /**\n     * 获取状态栏高度\n     */\n    public static int getStatusBarHight() {\n        if (statusbarheight != 0) {\n            return statusbarheight;\n        }\n        int result = 0;\n        int resourceId = Resources.getSystem().getIdentifier(\"status_bar_height\", \"dimen\", \"android\");\n        if (resourceId > 0) {\n            statusbarheight = result = Resources.getSystem().getDimensionPixelSize(resourceId);\n        }\n        return result;\n    }\n\n    /**\n     * 获取底部导航栏高度(不显示则为0)\n     */\n    public static int getNavigationBarHeight(Context context) {\n        if (navbarheight != 0) {\n            return navbarheight;\n        }\n        return navbarheight = getRealScreenHeight(context) - getScreenHeight();\n    }\n\n    /**\n     * 获取底部导航栏高度(无论显示与否)\n     */\n    public static int getRealNavigationBarHeight() {\n        int result = 0;\n        int resourceId = Resources.getSystem().getIdentifier(\"navigation_bar_height\", \"dimen\", \"android\");\n        if (resourceId > 0) {\n            result = Resources.getSystem().getDimensionPixelSize(resourceId);\n        }\n        return result;\n    }\n\n    /**\n     * 底部导航栏高度是否显示\n     */\n    public static boolean hasNavigationBar(Context context) {\n        return getNavigationBarHeight(context) > 0;\n    }\n\n    /**\n     * 获取真实屏幕高度(带虚拟按键)\n     */\n    public static int getRealScreenHeight(Context context) {\n        if (realScreenHeight != 0) {\n            return realScreenHeight;\n        }\n        WindowManager wm = (WindowManager) context\n                .getSystemService(Context.WINDOW_SERVICE);\n        assert wm != null;\n        Display display = wm.getDefaultDisplay();\n        DisplayMetrics dm = new DisplayMetrics();\n        if (Build.VERSION.SDK_INT >= 17) {//17以上可以直接获取 以下反射获取\n            display.getRealMetrics(dm);\n        } else {\n            @SuppressWarnings(\"rawtypes\")\n            Class c;\n            try {\n                c = Class.forName(\"android.view.Display\");\n                @SuppressWarnings(\"unchecked\")\n                Method method = c.getMethod(\"getRealMetrics\", DisplayMetrics.class);\n                method.invoke(display, dm);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        return realScreenHeight = dm.heightPixels;\n    }\n\n    /*用于横屏时获取真实宽度*/\n    public static int getRealScreenWidth(Context context) {\n        if (realScreenWidth != 0) {\n            return realScreenWidth;\n        }\n        WindowManager wm = (WindowManager) context\n                .getSystemService(Context.WINDOW_SERVICE);\n        assert wm != null;\n        Display display = wm.getDefaultDisplay();\n        DisplayMetrics dm = new DisplayMetrics();\n        if (Build.VERSION.SDK_INT >= 17) {//17以上可以直接获取 以下反射获取\n            display.getRealMetrics(dm);\n        } else {\n            @SuppressWarnings(\"rawtypes\")\n            Class c;\n            try {\n                c = Class.forName(\"android.view.Display\");\n                @SuppressWarnings(\"unchecked\")\n                Method method = c.getMethod(\"getRealMetrics\", DisplayMetrics.class);\n                method.invoke(display, dm);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        return realScreenWidth = dm.widthPixels;\n    }\n\n    /**\n     * 获取view的矩形坐标\n     */\n    public RectF getViewRectF(View view) {\n        int[] location = new int[2];\n        view.getLocationOnScreen(location);\n        return new RectF(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight());\n    }\n\n    /**\n     * 判断是否触摸在view上\n     */\n    public boolean isViewTouched(View view, float rawX, float rawY) {\n        return getViewRectF(view).contains(rawX, rawY);\n    }\n\n    public boolean isViewTouched(View view, MotionEvent event) {\n        // event.getX(); 获取相对于控件自身左上角的 x 坐标值\n        // event.getY(); 获取相对于控件自身左上角的 y 坐标值\n        float rawX = event.getRawX(); // 获取相对于屏幕左上角的 x 坐标值\n        float rawY = event.getRawY();// 获取相对于屏幕左上角的 y 坐标值\n        return isViewTouched(view, rawX, rawY);\n    }\n\n    /**\n     * 判断一个view的矩形是否包含另一view的矩形\n     */\n    public boolean containsRectF(View view1, View view2) {\n        return getViewRectF(view1).contains(getViewRectF(view2));\n    }\n\n    public boolean isInRectF(RectF rectF, float rawX, float rawY) {\n        return rectF.contains(rawX, rawY);\n    }\n\n    /**\n     * 获取软键盘高度(不显示则为0)\n     */\n    public static int getSoftInputHeight(Activity activity) {\n        if (activity == null || activity.isFinishing()) return 0;\n        //获取显示区域\n        Rect rect = new Rect();\n        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);\n        //rect.bottom为显示区域底部高度(不包含键盘) 屏幕高度减去显示区域高度 即为软键盘高度\n        return screenHeight - rect.bottom;\n    }\n\n    /**\n     * 软件盘是否显示\n     */\n    public static boolean isSoftInputShown(Activity activity) {\n        return getSoftInputHeight(activity) > 0;\n    }\n\n    public static int getImageMaxEdge() {\n        return (int) (165.0 / 320.0 * screenWidth);\n    }\n\n    public static int getImageMinEdge() {\n        return (int) (76.0 / 320.0 * screenWidth);\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/utils/StringUtils.java",
    "content": "package com.tophold.trade.utils;\n\nimport java.util.List;\nimport java.util.Random;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/11/23 10:25\n * 描 述 ：\n * ============================================================\n **/\npublic class StringUtils {\n\n    public static boolean isEmptyString(String str) {\n        if (str == null || str.isEmpty()) return true;\n        return false;\n    }\n\n    public static boolean isNotEmptyString(String str) {\n        return !isEmptyString(str);\n    }\n\n    public static boolean isEmptyList(List list) {\n        if (list == null || list.isEmpty()) return true;\n        return false;\n    }\n\n    public static boolean isNotEmptyList(List list) {\n        return !isEmptyList(list);\n    }\n\n\n    public static boolean isBlank(String... strs) {\n        for (String str : strs) {\n            if (str == null || str.equals(\"\")) return true;\n        }\n        return false;\n    }\n\n    public static boolean isTrimBlank(String... strs) {\n        for (String str : strs) {\n            if (str == null || str.trim().equals(\"\")) return true;\n        }\n        return false;\n    }\n\n    public static boolean isEmpty(List list) {\n        if (list == null || list.size() == 0) return true;\n        return false;\n    }\n\n    /**\n     * 随机获取[m,n]之间的一个数字\n     *\n     * @param min\n     * @param max\n     * @return\n     */\n    public static int getRadomNum(int min, int max) {\n        Random rdm = new Random();\n        return rdm.nextInt(max - min + 1) + min;\n    }\n    public static String getString(){\n        return getRadomNum(0,1)==0?null:\"sdaas\";\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/utils/TimeConstants.java",
    "content": "package com.tophold.trade.utils;\n\nimport android.support.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * <pre>\n *     author: Blankj\n *     blog  : http://blankj.com\n *     time  : 2017/03/13\n *     desc  : 时间相关常量\n * </pre>\n */\npublic final class TimeConstants {\n\n    /**\n     * 毫秒与毫秒的倍数\n     */\n    public static final int MSEC = 1;\n    /**\n     * 秒与毫秒的倍数\n     */\n    public static final int SEC  = 1000;\n    /**\n     * 分与毫秒的倍数\n     */\n    public static final int MIN  = 60000;\n    /**\n     * 时与毫秒的倍数\n     */\n    public static final int HOUR = 3600000;\n    /**\n     * 天与毫秒的倍数\n     */\n    public static final int DAY  = 86400000;\n\n    @IntDef({MSEC, SEC, MIN, HOUR, DAY})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface Unit {\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/utils/TimeUtils.java",
    "content": "package com.tophold.trade.utils;\n\n\nimport java.text.DateFormat;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.Locale;\n\n/**\n * <pre>\n *     author: Blankj\n *     blog  : http://blankj.com\n *     time  : 2016/08/02\n *     desc  : 时间相关工具类\n * </pre>\n */\npublic final class TimeUtils {\n\n    /**\n     * <p>在工具类中经常使用到工具类的格式化描述，这个主要是一个日期的操作类，所以日志格式主要使用 SimpleDateFormat的定义格式.</p>\n     * 格式的意义如下： 日期和时间模式 <br>\n     * <p>日期和时间格式由日期和时间模式字符串指定。在日期和时间模式字符串中，未加引号的字母 'A' 到 'Z' 和 'a' 到 'z'\n     * 被解释为模式字母，用来表示日期或时间字符串元素。文本可以使用单引号 (') 引起来，以免进行解释。\"''\"\n     * 表示单引号。所有其他字符均不解释；只是在格式化时将它们简单复制到输出字符串，或者在分析时与输入字符串进行匹配。\n     * </p>\n     * 定义了以下模式字母（所有其他字符 'A' 到 'Z' 和 'a' 到 'z' 都被保留）： <br>\n     * <table border=\"1\" cellspacing=\"1\" cellpadding=\"1\" summary=\"Chart shows format letters, date/time component,\n     * presentation, and examples.\">\n     * <tr>\n     * <th align=\"left\">字母</th>\n     * <th align=\"left\">日期或时间元素</th>\n     * <th align=\"left\">表示</th>\n     * <th align=\"left\">示例</th>\n     * </tr>\n     * <tr>\n     * <td><code>G</code></td>\n     * <td>Era 标志符</td>\n     * <td>Text</td>\n     * <td><code>AD</code></td>\n     * </tr>\n     * <tr>\n     * <td><code>y</code> </td>\n     * <td>年 </td>\n     * <td>Year </td>\n     * <td><code>1996</code>; <code>96</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>M</code> </td>\n     * <td>年中的月份 </td>\n     * <td>Month </td>\n     * <td><code>July</code>; <code>Jul</code>; <code>07</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>w</code> </td>\n     * <td>年中的周数 </td>\n     * <td>Number </td>\n     * <td><code>27</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>W</code> </td>\n     * <td>月份中的周数 </td>\n     * <td>Number </td>\n     * <td><code>2</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>D</code> </td>\n     * <td>年中的天数 </td>\n     * <td>Number </td>\n     * <td><code>189</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>d</code> </td>\n     * <td>月份中的天数 </td>\n     * <td>Number </td>\n     * <td><code>10</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>F</code> </td>\n     * <td>月份中的星期 </td>\n     * <td>Number </td>\n     * <td><code>2</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>E</code> </td>\n     * <td>星期中的天数 </td>\n     * <td>Text </td>\n     * <td><code>Tuesday</code>; <code>Tue</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>a</code> </td>\n     * <td>Am/pm 标记 </td>\n     * <td>Text </td>\n     * <td><code>PM</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>H</code> </td>\n     * <td>一天中的小时数（0-23） </td>\n     * <td>Number </td>\n     * <td><code>0</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>k</code> </td>\n     * <td>一天中的小时数（1-24） </td>\n     * <td>Number </td>\n     * <td><code>24</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>K</code> </td>\n     * <td>am/pm 中的小时数（0-11） </td>\n     * <td>Number </td>\n     * <td><code>0</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>h</code> </td>\n     * <td>am/pm 中的小时数（1-12） </td>\n     * <td>Number </td>\n     * <td><code>12</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>m</code> </td>\n     * <td>小时中的分钟数 </td>\n     * <td>Number </td>\n     * <td><code>30</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>s</code> </td>\n     * <td>分钟中的秒数 </td>\n     * <td>Number </td>\n     * <td><code>55</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>S</code> </td>\n     * <td>毫秒数 </td>\n     * <td>Number </td>\n     * <td><code>978</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>z</code> </td>\n     * <td>时区 </td>\n     * <td>General time zone </td>\n     * <td><code>Pacific Standard Time</code>; <code>PST</code>; <code>GMT-08:00</code> </td>\n     * </tr>\n     * <tr>\n     * <td><code>Z</code> </td>\n     * <td>时区 </td>\n     * <td>RFC 822 time zone </td>\n     * <td><code>-0800</code> </td>\n     * </tr>\n     * </table>\n     * <pre>\n     *                                             HH:mm    15:44\n     *                                            h:mm a    3:44 下午\n     *                                           HH:mm z    15:44 CST\n     *                                           HH:mm Z    15:44 +0800\n     *                                        HH:mm zzzz    15:44 中国标准时间\n     *                                          HH:mm:ss    15:44:40\n     *                                        yyyy-MM-dd    2016-08-12\n     *                                  yyyy-MM-dd HH:mm    2016-08-12 15:44\n     *                               yyyy-MM-dd HH:mm:ss    2016-08-12 15:44:40\n     *                          yyyy-MM-dd HH:mm:ss zzzz    2016-08-12 15:44:40 中国标准时间\n     *                     EEEE yyyy-MM-dd HH:mm:ss zzzz    星期五 2016-08-12 15:44:40 中国标准时间\n     *                          yyyy-MM-dd HH:mm:ss.SSSZ    2016-08-12 15:44:40.461+0800\n     *                        yyyy-MM-dd'T'HH:mm:ss.SSSZ    2016-08-12T15:44:40.461+0800\n     *                      yyyy.MM.dd G 'at' HH:mm:ss z    2016.08.12 公元 at 15:44:40 CST\n     *                                            K:mm a    3:44 下午\n     *                                  EEE, MMM d, ''yy    星期五, 八月 12, '16\n     *                             hh 'o''clock' a, zzzz    03 o'clock 下午, 中国标准时间\n     *                      yyyyy.MMMMM.dd GGG hh:mm aaa    02016.八月.12 公元 03:44 下午\n     *                        EEE, d MMM yyyy HH:mm:ss Z    星期五, 12 八月 2016 15:44:40 +0800\n     *                                     yyMMddHHmmssZ    160812154440+0800\n     *                        yyyy-MM-dd'T'HH:mm:ss.SSSZ    2016-08-12T15:44:40.461+0800\n     * EEEE 'DATE('yyyy-MM-dd')' 'TIME('HH:mm:ss')' zzzz    星期五 DATE(2016-08-12) TIME(15:44:40) 中国标准时间\n     * </pre>\n     * 注意：SimpleDateFormat不是线程安全的，线程安全需用{@code ThreadLocal<SimpleDateFormat>}\n     */\n\n    private static final DateFormat DEFAULT_FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\", Locale.getDefault());\n\n    private TimeUtils() {\n        throw new UnsupportedOperationException(\"u can't instantiate me...\");\n    }\n\n    /**\n     * 将时间戳转为时间字符串\n     * <p>格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param millis 毫秒时间戳\n     * @return 时间字符串\n     */\n    public static String millis2String(final long millis) {\n        return millis2String(millis, DEFAULT_FORMAT);\n    }\n\n    /**\n     * 将时间戳转为时间字符串\n     * <p>格式为format</p>\n     *\n     * @param millis 毫秒时间戳\n     * @param format 时间格式\n     * @return 时间字符串\n     */\n    public static String millis2String(final long millis, final DateFormat format) {\n        return format.format(new Date(millis));\n    }\n\n    /**\n     * 将时间字符串转为时间戳\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 毫秒时间戳\n     */\n    public static long string2Millis(final String time) {\n        return string2Millis(time, DEFAULT_FORMAT);\n    }\n\n    /**\n     * 将时间字符串转为时间戳\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 毫秒时间戳\n     */\n    public static long string2Millis(final String time, final DateFormat format) {\n        try {\n            return format.parse(time).getTime();\n        } catch (ParseException e) {\n            e.printStackTrace();\n        }\n        return -1;\n    }\n\n    /**\n     * 将时间字符串转为Date类型\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return Date类型\n     */\n    public static Date string2Date(final String time) {\n        return string2Date(time, DEFAULT_FORMAT);\n    }\n\n    /**\n     * 将时间字符串转为Date类型\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return Date类型\n     */\n    public static Date string2Date(final String time, final DateFormat format) {\n        try {\n            return format.parse(time);\n        } catch (ParseException e) {\n            e.printStackTrace();\n        }\n        return null;\n    }\n\n    /**\n     * 将Date类型转为时间字符串\n     * <p>格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param date Date类型时间\n     * @return 时间字符串\n     */\n    public static String date2String(final Date date) {\n        return date2String(date, DEFAULT_FORMAT);\n    }\n\n    /**\n     * 将Date类型转为时间字符串\n     * <p>格式为format</p>\n     *\n     * @param date   Date类型时间\n     * @param format 时间格式\n     * @return 时间字符串\n     */\n    public static String date2String(final Date date, final DateFormat format) {\n        return format.format(date);\n    }\n\n    /**\n     * 将Date类型转为时间戳\n     *\n     * @param date Date类型时间\n     * @return 毫秒时间戳\n     */\n    public static long date2Millis(final Date date) {\n        return date.getTime();\n    }\n\n    /**\n     * 将时间戳转为Date类型\n     *\n     * @param millis 毫秒时间戳\n     * @return Date类型时间\n     */\n    public static Date millis2Date(final long millis) {\n        return new Date(millis);\n    }\n\n    /**\n     * 获取两个时间差（单位：unit）\n     * <p>time0和time1格式都为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time0 时间字符串0\n     * @param time1 时间字符串1\n     * @param unit  单位类型\n     *              <ul>\n     *              <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *              <li>{@link TimeConstants#SEC }: 秒</li>\n     *              <li>{@link TimeConstants#MIN }: 分</li>\n     *              <li>{@link TimeConstants#HOUR}: 小时</li>\n     *              <li>{@link TimeConstants#DAY }: 天</li>\n     *              </ul>\n     * @return unit时间戳\n     */\n    public static long getTimeSpan(final String time0, final String time1, @TimeConstants.Unit final int unit) {\n        return getTimeSpan(time0, time1, DEFAULT_FORMAT, unit);\n    }\n\n    /**\n     * 获取两个时间差（单位：unit）\n     * <p>time0和time1格式都为format</p>\n     *\n     * @param time0  时间字符串0\n     * @param time1  时间字符串1\n     * @param format 时间格式\n     * @param unit   单位类型\n     *               <ul>\n     *               <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *               <li>{@link TimeConstants#SEC }: 秒</li>\n     *               <li>{@link TimeConstants#MIN }: 分</li>\n     *               <li>{@link TimeConstants#HOUR}: 小时</li>\n     *               <li>{@link TimeConstants#DAY }: 天</li>\n     *               </ul>\n     * @return unit时间戳\n     */\n    public static long getTimeSpan(final String time0, final String time1, final DateFormat format, @TimeConstants.Unit final int unit) {\n        return millis2TimeSpan(Math.abs(string2Millis(time0, format) - string2Millis(time1, format)), unit);\n    }\n\n    /**\n     * 获取两个时间差（单位：unit）\n     *\n     * @param date0 Date类型时间0\n     * @param date1 Date类型时间1\n     * @param unit  单位类型\n     *              <ul>\n     *              <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *              <li>{@link TimeConstants#SEC }: 秒</li>\n     *              <li>{@link TimeConstants#MIN }: 分</li>\n     *              <li>{@link TimeConstants#HOUR}: 小时</li>\n     *              <li>{@link TimeConstants#DAY }: 天</li>\n     *              </ul>\n     * @return unit时间戳\n     */\n    public static long getTimeSpan(final Date date0, final Date date1, @TimeConstants.Unit final int unit) {\n        return millis2TimeSpan(Math.abs(date2Millis(date0) - date2Millis(date1)), unit);\n    }\n\n    /**\n     * 获取两个时间差（单位：unit）\n     *\n     * @param millis0 毫秒时间戳0\n     * @param millis1 毫秒时间戳1\n     * @param unit    单位类型\n     *                <ul>\n     *                <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                <li>{@link TimeConstants#SEC }: 秒</li>\n     *                <li>{@link TimeConstants#MIN }: 分</li>\n     *                <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                <li>{@link TimeConstants#DAY }: 天</li>\n     *                </ul>\n     * @return unit时间戳\n     */\n    public static long getTimeSpan(final long millis0, final long millis1, @TimeConstants.Unit final int unit) {\n        return millis2TimeSpan(Math.abs(millis0 - millis1), unit);\n    }\n\n    /**\n     * 获取合适型两个时间差\n     * <p>time0和time1格式都为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time0     时间字符串0\n     * @param time1     时间字符串1\n     * @param precision 精度\n     *                  <p>precision = 0，返回null</p>\n     *                  <p>precision = 1，返回天</p>\n     *                  <p>precision = 2，返回天和小时</p>\n     *                  <p>precision = 3，返回天、小时和分钟</p>\n     *                  <p>precision = 4，返回天、小时、分钟和秒</p>\n     *                  <p>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</p>\n     * @return 合适型两个时间差\n     */\n    public static String getFitTimeSpan(final String time0, final String time1, final int precision) {\n        return millis2FitTimeSpan(Math.abs(string2Millis(time0, DEFAULT_FORMAT) - string2Millis(time1, DEFAULT_FORMAT)), precision);\n    }\n\n    /**\n     * 获取合适型两个时间差\n     * <p>time0和time1格式都为format</p>\n     *\n     * @param time0     时间字符串0\n     * @param time1     时间字符串1\n     * @param format    时间格式\n     * @param precision 精度\n     *                  <p>precision = 0，返回null</p>\n     *                  <p>precision = 1，返回天</p>\n     *                  <p>precision = 2，返回天和小时</p>\n     *                  <p>precision = 3，返回天、小时和分钟</p>\n     *                  <p>precision = 4，返回天、小时、分钟和秒</p>\n     *                  <p>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</p>\n     * @return 合适型两个时间差\n     */\n    public static String getFitTimeSpan(final String time0, final String time1, final DateFormat format, final int precision) {\n        return millis2FitTimeSpan(Math.abs(string2Millis(time0, format) - string2Millis(time1, format)), precision);\n    }\n\n    /**\n     * 获取合适型两个时间差\n     *\n     * @param date0     Date类型时间0\n     * @param date1     Date类型时间1\n     * @param precision 精度\n     *                  <p>precision = 0，返回null</p>\n     *                  <p>precision = 1，返回天</p>\n     *                  <p>precision = 2，返回天和小时</p>\n     *                  <p>precision = 3，返回天、小时和分钟</p>\n     *                  <p>precision = 4，返回天、小时、分钟和秒</p>\n     *                  <p>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</p>\n     * @return 合适型两个时间差\n     */\n    public static String getFitTimeSpan(final Date date0, final Date date1, final int precision) {\n        return millis2FitTimeSpan(Math.abs(date2Millis(date0) - date2Millis(date1)), precision);\n    }\n\n    /**\n     * 获取合适型两个时间差\n     *\n     * @param millis0   毫秒时间戳1\n     * @param millis1   毫秒时间戳2\n     * @param precision 精度\n     *                  <p>precision = 0，返回null</p>\n     *                  <p>precision = 1，返回天</p>\n     *                  <p>precision = 2，返回天和小时</p>\n     *                  <p>precision = 3，返回天、小时和分钟</p>\n     *                  <p>precision = 4，返回天、小时、分钟和秒</p>\n     *                  <p>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</p>\n     * @return 合适型两个时间差\n     */\n    public static String getFitTimeSpan(final long millis0, final long millis1, final int precision) {\n        return millis2FitTimeSpan(Math.abs(millis0 - millis1), precision);\n    }\n\n    /**\n     * 获取当前毫秒时间戳\n     *\n     * @return 毫秒时间戳\n     */\n    public static long getNowMills() {\n        return System.currentTimeMillis();\n    }\n\n    /**\n     * 获取当前时间字符串\n     * <p>格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @return 时间字符串\n     */\n    public static String getNowString() {\n        return millis2String(System.currentTimeMillis(), DEFAULT_FORMAT);\n    }\n\n    /**\n     * 获取当前时间字符串\n     * <p>格式为format</p>\n     *\n     * @param format 时间格式\n     * @return 时间字符串\n     */\n    public static String getNowString(final DateFormat format) {\n        return millis2String(System.currentTimeMillis(), format);\n    }\n\n    /**\n     * 获取当前Date\n     *\n     * @return Date类型时间\n     */\n    public static Date getNowDate() {\n        return new Date();\n    }\n\n    /**\n     * 获取与当前时间的差（单位：unit）\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @param unit 单位类型\n     *             <ul>\n     *             <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *             <li>{@link TimeConstants#SEC }: 秒</li>\n     *             <li>{@link TimeConstants#MIN }: 分</li>\n     *             <li>{@link TimeConstants#HOUR}: 小时</li>\n     *             <li>{@link TimeConstants#DAY }: 天</li>\n     *             </ul>\n     * @return unit时间戳\n     */\n    public static long getTimeSpanByNow(final String time, @TimeConstants.Unit final int unit) {\n        return getTimeSpan(getNowString(), time, DEFAULT_FORMAT, unit);\n    }\n\n    /**\n     * 获取与当前时间的差（单位：unit）\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @param unit   单位类型\n     *               <ul>\n     *               <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *               <li>{@link TimeConstants#SEC }: 秒</li>\n     *               <li>{@link TimeConstants#MIN }: 分</li>\n     *               <li>{@link TimeConstants#HOUR}: 小时</li>\n     *               <li>{@link TimeConstants#DAY }: 天</li>\n     *               </ul>\n     * @return unit时间戳\n     */\n    public static long getTimeSpanByNow(final String time, final DateFormat format, @TimeConstants.Unit final int unit) {\n        return getTimeSpan(getNowString(format), time, format, unit);\n    }\n\n    /**\n     * 获取与当前时间的差（单位：unit）\n     *\n     * @param date Date类型时间\n     * @param unit 单位类型\n     *             <ul>\n     *             <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *             <li>{@link TimeConstants#SEC }: 秒</li>\n     *             <li>{@link TimeConstants#MIN }: 分</li>\n     *             <li>{@link TimeConstants#HOUR}: 小时</li>\n     *             <li>{@link TimeConstants#DAY }: 天</li>\n     *             </ul>\n     * @return unit时间戳\n     */\n    public static long getTimeSpanByNow(final Date date, @TimeConstants.Unit final int unit) {\n        return getTimeSpan(new Date(), date, unit);\n    }\n\n    /**\n     * 获取与当前时间的差（单位：unit）\n     *\n     * @param millis 毫秒时间戳\n     * @param unit   单位类型\n     *               <ul>\n     *               <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *               <li>{@link TimeConstants#SEC }: 秒</li>\n     *               <li>{@link TimeConstants#MIN }: 分</li>\n     *               <li>{@link TimeConstants#HOUR}: 小时</li>\n     *               <li>{@link TimeConstants#DAY }: 天</li>\n     *               </ul>\n     * @return unit时间戳\n     */\n    public static long getTimeSpanByNow(final long millis, @TimeConstants.Unit final int unit) {\n        return getTimeSpan(System.currentTimeMillis(), millis, unit);\n    }\n\n    /**\n     * 获取合适型与当前时间的差\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time      时间字符串\n     * @param precision 精度\n     *                  <ul>\n     *                  <li>precision = 0，返回null</li>\n     *                  <li>precision = 1，返回天</li>\n     *                  <li>precision = 2，返回天和小时</li>\n     *                  <li>precision = 3，返回天、小时和分钟</li>\n     *                  <li>precision = 4，返回天、小时、分钟和秒</li>\n     *                  <li>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</li>\n     *                  </ul>\n     * @return 合适型与当前时间的差\n     */\n    public static String getFitTimeSpanByNow(final String time, final int precision) {\n        return getFitTimeSpan(getNowString(), time, DEFAULT_FORMAT, precision);\n    }\n\n    /**\n     * 获取合适型与当前时间的差\n     * <p>time格式为format</p>\n     *\n     * @param time      时间字符串\n     * @param format    时间格式\n     * @param precision 精度\n     *                  <ul>\n     *                  <li>precision = 0，返回null</li>\n     *                  <li>precision = 1，返回天</li>\n     *                  <li>precision = 2，返回天和小时</li>\n     *                  <li>precision = 3，返回天、小时和分钟</li>\n     *                  <li>precision = 4，返回天、小时、分钟和秒</li>\n     *                  <li>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</li>\n     *                  </ul>\n     * @return 合适型与当前时间的差\n     */\n    public static String getFitTimeSpanByNow(final String time, final DateFormat format, final int precision) {\n        return getFitTimeSpan(getNowString(format), time, format, precision);\n    }\n\n    /**\n     * 获取合适型与当前时间的差\n     *\n     * @param date      Date类型时间\n     * @param precision 精度\n     *                  <ul>\n     *                  <li>precision = 0，返回null</li>\n     *                  <li>precision = 1，返回天</li>\n     *                  <li>precision = 2，返回天和小时</li>\n     *                  <li>precision = 3，返回天、小时和分钟</li>\n     *                  <li>precision = 4，返回天、小时、分钟和秒</li>\n     *                  <li>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</li>\n     *                  </ul>\n     * @return 合适型与当前时间的差\n     */\n    public static String getFitTimeSpanByNow(final Date date, final int precision) {\n        return getFitTimeSpan(getNowDate(), date, precision);\n    }\n\n    /**\n     * 获取合适型与当前时间的差\n     *\n     * @param millis    毫秒时间戳\n     * @param precision 精度\n     *                  <ul>\n     *                  <li>precision = 0，返回null</li>\n     *                  <li>precision = 1，返回天</li>\n     *                  <li>precision = 2，返回天和小时</li>\n     *                  <li>precision = 3，返回天、小时和分钟</li>\n     *                  <li>precision = 4，返回天、小时、分钟和秒</li>\n     *                  <li>precision &gt;= 5，返回天、小时、分钟、秒和毫秒</li>\n     *                  </ul>\n     * @return 合适型与当前时间的差\n     */\n    public static String getFitTimeSpanByNow(final long millis, final int precision) {\n        return getFitTimeSpan(System.currentTimeMillis(), millis, precision);\n    }\n\n    /**\n     * 获取友好型与当前时间的差\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 友好型与当前时间的差\n     * <ul>\n     * <li>如果小于1秒钟内，显示刚刚</li>\n     * <li>如果在1分钟内，显示XXX秒前</li>\n     * <li>如果在1小时内，显示XXX分钟前</li>\n     * <li>如果在1小时外的今天内，显示今天15:32</li>\n     * <li>如果是昨天的，显示昨天15:32</li>\n     * <li>其余显示，2016-10-15</li>\n     * <li>时间不合法的情况全部日期和时间信息，如星期六 十月 27 14:21:20 CST 2007</li>\n     * </ul>\n     */\n    public static String getFriendlyTimeSpanByNow(final String time) {\n        return getFriendlyTimeSpanByNow(time, DEFAULT_FORMAT);\n    }\n\n    /**\n     * 获取友好型与当前时间的差\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 友好型与当前时间的差\n     * <ul>\n     * <li>如果小于1秒钟内，显示刚刚</li>\n     * <li>如果在1分钟内，显示XXX秒前</li>\n     * <li>如果在1小时内，显示XXX分钟前</li>\n     * <li>如果在1小时外的今天内，显示今天15:32</li>\n     * <li>如果是昨天的，显示昨天15:32</li>\n     * <li>其余显示，2016-10-15</li>\n     * <li>时间不合法的情况全部日期和时间信息，如星期六 十月 27 14:21:20 CST 2007</li>\n     * </ul>\n     */\n    public static String getFriendlyTimeSpanByNow(final String time, final DateFormat format) {\n        return getFriendlyTimeSpanByNow(string2Millis(time, format));\n    }\n\n    /**\n     * 获取友好型与当前时间的差\n     *\n     * @param date Date类型时间\n     * @return 友好型与当前时间的差\n     * <ul>\n     * <li>如果小于1秒钟内，显示刚刚</li>\n     * <li>如果在1分钟内，显示XXX秒前</li>\n     * <li>如果在1小时内，显示XXX分钟前</li>\n     * <li>如果在1小时外的今天内，显示今天15:32</li>\n     * <li>如果是昨天的，显示昨天15:32</li>\n     * <li>其余显示，2016-10-15</li>\n     * <li>时间不合法的情况全部日期和时间信息，如星期六 十月 27 14:21:20 CST 2007</li>\n     * </ul>\n     */\n    public static String getFriendlyTimeSpanByNow(final Date date) {\n        return getFriendlyTimeSpanByNow(date.getTime());\n    }\n\n    /**\n     * 获取友好型与当前时间的差\n     *\n     * @param millis 毫秒时间戳\n     * @return 友好型与当前时间的差\n     * <ul>\n     * <li>如果小于1秒钟内，显示刚刚</li>\n     * <li>如果在1分钟内，显示XXX秒前</li>\n     * <li>如果在1小时内，显示XXX分钟前</li>\n     * <li>如果在1小时外的今天内，显示今天15:32</li>\n     * <li>如果是昨天的，显示昨天15:32</li>\n     * <li>其余显示，2016-10-15</li>\n     * <li>时间不合法的情况全部日期和时间信息，如星期六 十月 27 14:21:20 CST 2007</li>\n     * </ul>\n     */\n    public static String getFriendlyTimeSpanByNow(final long millis) {\n        long now = System.currentTimeMillis();\n        long span = now - millis;\n        if (span < 0)\n            return String.format(\"%tc\", millis);// U can read http://www.apihome.cn/api/java/Formatter.html to understand it.\n        if (span < 1000) {\n            return \"刚刚\";\n        } else if (span < TimeConstants.MIN) {\n            return String.format(Locale.getDefault(), \"%d秒前\", span / TimeConstants.SEC);\n        } else if (span < TimeConstants.HOUR) {\n            return String.format(Locale.getDefault(), \"%d分钟前\", span / TimeConstants.MIN);\n        }\n        // 获取当天00:00\n        long wee = getWeeOfToday();\n        if (millis >= wee) {\n            return String.format(\"今天%tR\", millis);\n        } else if (millis >= wee - TimeConstants.DAY) {\n            return String.format(\"昨天%tR\", millis);\n        } else {\n            return String.format(\"%tF\", millis);\n        }\n    }\n\n    private static long getWeeOfToday() {\n        Calendar cal = Calendar.getInstance();\n        cal.set(Calendar.HOUR_OF_DAY, 0);\n        cal.set(Calendar.SECOND, 0);\n        cal.set(Calendar.MINUTE, 0);\n        cal.set(Calendar.MILLISECOND, 0);\n        return cal.getTimeInMillis();\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间戳\n     *\n     * @param millis   给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间戳\n     */\n    public static long getMillis(final long millis, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return millis + timeSpan2Millis(timeSpan, unit);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间戳\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time     给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间戳\n     */\n    public static long getMillis(final String time, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return getMillis(time, DEFAULT_FORMAT, timeSpan, unit);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间戳\n     * <p>time格式为format</p>\n     *\n     * @param time     给定时间\n     * @param format   时间格式\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间戳\n     */\n    public static long getMillis(final String time, final DateFormat format, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return string2Millis(time, format) + timeSpan2Millis(timeSpan, unit);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间戳\n     *\n     * @param date     给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间戳\n     */\n    public static long getMillis(final Date date, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return date2Millis(date) + timeSpan2Millis(timeSpan, unit);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间字符串\n     * <p>格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param millis   给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间字符串\n     */\n    public static String getString(final long millis, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return getString(millis, DEFAULT_FORMAT, timeSpan, unit);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间字符串\n     * <p>格式为format</p>\n     *\n     * @param millis   给定时间\n     * @param format   时间格式\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间字符串\n     */\n    public static String getString(final long millis, final DateFormat format, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return millis2String(millis + timeSpan2Millis(timeSpan, unit), format);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间字符串\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time     给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间字符串\n     */\n    public static String getString(final String time, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return getString(time, DEFAULT_FORMAT, timeSpan, unit);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间字符串\n     * <p>格式为format</p>\n     *\n     * @param time     给定时间\n     * @param format   时间格式\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间字符串\n     */\n    public static String getString(final String time, final DateFormat format, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return millis2String(string2Millis(time, format) + timeSpan2Millis(timeSpan, unit), format);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间字符串\n     * <p>格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param date     给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间字符串\n     */\n    public static String getString(final Date date, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return getString(date, DEFAULT_FORMAT, timeSpan, unit);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的时间字符串\n     * <p>格式为format</p>\n     *\n     * @param date     给定时间\n     * @param format   时间格式\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的时间字符串\n     */\n    public static String getString(final Date date, final DateFormat format, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return millis2String(date2Millis(date) + timeSpan2Millis(timeSpan, unit), format);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的Date\n     *\n     * @param millis   给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的Date\n     */\n    public static Date getDate(final long millis, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return millis2Date(millis + timeSpan2Millis(timeSpan, unit));\n    }\n\n    /**\n     * 获取与给定时间等于时间差的Date\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time     给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的Date\n     */\n    public static Date getDate(final String time, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return getDate(time, DEFAULT_FORMAT, timeSpan, unit);\n    }\n\n    /**\n     * 获取与给定时间等于时间差的Date\n     * <p>格式为format</p>\n     *\n     * @param time     给定时间\n     * @param format   时间格式\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的Date\n     */\n    public static Date getDate(final String time, final DateFormat format, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return millis2Date(string2Millis(time, format) + timeSpan2Millis(timeSpan, unit));\n    }\n\n    /**\n     * 获取与给定时间等于时间差的Date\n     *\n     * @param date     给定时间\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与给定时间等于时间差的Date\n     */\n    public static Date getDate(final Date date, final long timeSpan, @TimeConstants.Unit final int unit) {\n        return millis2Date(date2Millis(date) + timeSpan2Millis(timeSpan, unit));\n    }\n\n    /**\n     * 获取与当前时间等于时间差的时间戳\n     *\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与当前时间等于时间差的时间戳\n     */\n    public static long getMillisByNow(final long timeSpan, @TimeConstants.Unit final int unit) {\n        return getMillis(getNowMills(), timeSpan, unit);\n    }\n\n    /**\n     * 获取与当前时间等于时间差的时间字符串\n     * <p>格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与当前时间等于时间差的时间字符串\n     */\n    public static String getStringByNow(final long timeSpan, @TimeConstants.Unit final int unit) {\n        return getStringByNow(timeSpan, DEFAULT_FORMAT, unit);\n    }\n\n    /**\n     * 获取与当前时间等于时间差的时间字符串\n     * <p>格式为format</p>\n     *\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param format   时间格式\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与当前时间等于时间差的时间字符串\n     */\n    public static String getStringByNow(final long timeSpan, final DateFormat format, @TimeConstants.Unit final int unit) {\n        return getString(getNowMills(), format, timeSpan, unit);\n    }\n\n    /**\n     * 获取与当前时间等于时间差的Date\n     *\n     * @param timeSpan 时间差的毫秒时间戳\n     * @param unit     单位类型\n     *                 <ul>\n     *                 <li>{@link TimeConstants#MSEC}: 毫秒</li>\n     *                 <li>{@link TimeConstants#SEC }: 秒</li>\n     *                 <li>{@link TimeConstants#MIN }: 分</li>\n     *                 <li>{@link TimeConstants#HOUR}: 小时</li>\n     *                 <li>{@link TimeConstants#DAY }: 天</li>\n     *                 </ul>\n     * @return 与当前时间等于时间差的Date\n     */\n    public static Date getDateByNow(final long timeSpan, @TimeConstants.Unit final int unit) {\n        return getDate(getNowMills(), timeSpan, unit);\n    }\n\n    /**\n     * 判断是否今天\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return {@code true}: 是<br>{@code false}: 否\n     */\n    public static boolean isToday(final String time) {\n        return isToday(string2Millis(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 判断是否今天\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return {@code true}: 是<br>{@code false}: 否\n     */\n    public static boolean isToday(final String time, final DateFormat format) {\n        return isToday(string2Millis(time, format));\n    }\n\n    /**\n     * 判断是否今天\n     *\n     * @param date Date类型时间\n     * @return {@code true}: 是<br>{@code false}: 否\n     */\n    public static boolean isToday(final Date date) {\n        return isToday(date.getTime());\n    }\n\n    /**\n     * 判断是否今天\n     *\n     * @param millis 毫秒时间戳\n     * @return {@code true}: 是<br>{@code false}: 否\n     */\n    public static boolean isToday(final long millis) {\n        long wee = getWeeOfToday();\n        return millis >= wee && millis < wee + TimeConstants.DAY;\n    }\n\n    /**\n     * 判断是否闰年\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return {@code true}: 闰年<br>{@code false}: 平年\n     */\n    public static boolean isLeapYear(final String time) {\n        return isLeapYear(string2Date(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 判断是否闰年\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return {@code true}: 闰年<br>{@code false}: 平年\n     */\n    public static boolean isLeapYear(final String time, final DateFormat format) {\n        return isLeapYear(string2Date(time, format));\n    }\n\n    /**\n     * 判断是否闰年\n     *\n     * @param date Date类型时间\n     * @return {@code true}: 闰年<br>{@code false}: 平年\n     */\n    public static boolean isLeapYear(final Date date) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(date);\n        int year = cal.get(Calendar.YEAR);\n        return isLeapYear(year);\n    }\n\n    /**\n     * 判断是否闰年\n     *\n     * @param millis 毫秒时间戳\n     * @return {@code true}: 闰年<br>{@code false}: 平年\n     */\n    public static boolean isLeapYear(final long millis) {\n        return isLeapYear(millis2Date(millis));\n    }\n\n    /**\n     * 判断是否闰年\n     *\n     * @param year 年份\n     * @return {@code true}: 闰年<br>{@code false}: 平年\n     */\n    public static boolean isLeapYear(final int year) {\n        return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;\n    }\n\n    /**\n     * 获取中式星期\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 中式星期\n     */\n    public static String getChineseWeek(final String time) {\n        return getChineseWeek(string2Date(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 获取中式星期\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 中式星期\n     */\n    public static String getChineseWeek(final String time, final DateFormat format) {\n        return getChineseWeek(string2Date(time, format));\n    }\n\n    /**\n     * 获取中式星期\n     *\n     * @param date Date类型时间\n     * @return 中式星期\n     */\n    public static String getChineseWeek(final Date date) {\n        return new SimpleDateFormat(\"E\", Locale.CHINA).format(date);\n    }\n\n    /**\n     * 获取中式星期\n     *\n     * @param millis 毫秒时间戳\n     * @return 中式星期\n     */\n    public static String getChineseWeek(final long millis) {\n        return getChineseWeek(new Date(millis));\n    }\n\n    /**\n     * 获取美式星期\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 美式星期\n     */\n    public static String getUSWeek(final String time) {\n        return getUSWeek(string2Date(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 获取美式星期\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 美式星期\n     */\n    public static String getUSWeek(final String time, final DateFormat format) {\n        return getUSWeek(string2Date(time, format));\n    }\n\n    /**\n     * 获取美式星期\n     *\n     * @param date Date类型时间\n     * @return 美式星期\n     */\n    public static String getUSWeek(final Date date) {\n        return new SimpleDateFormat(\"EEEE\", Locale.US).format(date);\n    }\n\n    /**\n     * 获取美式星期\n     *\n     * @param millis 毫秒时间戳\n     * @return 美式星期\n     */\n    public static String getUSWeek(final long millis) {\n        return getUSWeek(new Date(millis));\n    }\n\n    /**\n     * 获取星期索引\n     * <p>注意：周日的Index才是1，周六为7</p>\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 1...7\n     * @see Calendar#SUNDAY\n     * @see Calendar#MONDAY\n     * @see Calendar#TUESDAY\n     * @see Calendar#WEDNESDAY\n     * @see Calendar#THURSDAY\n     * @see Calendar#FRIDAY\n     * @see Calendar#SATURDAY\n     */\n    public static int getWeekIndex(final String time) {\n        return getWeekIndex(string2Date(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 获取星期索引\n     * <p>注意：周日的Index才是1，周六为7</p>\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 1...7\n     * @see Calendar#SUNDAY\n     * @see Calendar#MONDAY\n     * @see Calendar#TUESDAY\n     * @see Calendar#WEDNESDAY\n     * @see Calendar#THURSDAY\n     * @see Calendar#FRIDAY\n     * @see Calendar#SATURDAY\n     */\n    public static int getWeekIndex(final String time, final DateFormat format) {\n        return getWeekIndex(string2Date(time, format));\n    }\n\n    /**\n     * 获取星期索引\n     * <p>注意：周日的Index才是1，周六为7</p>\n     *\n     * @param date Date类型时间\n     * @return 1...7\n     * @see Calendar#SUNDAY\n     * @see Calendar#MONDAY\n     * @see Calendar#TUESDAY\n     * @see Calendar#WEDNESDAY\n     * @see Calendar#THURSDAY\n     * @see Calendar#FRIDAY\n     * @see Calendar#SATURDAY\n     */\n    public static int getWeekIndex(final Date date) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(date);\n        return cal.get(Calendar.DAY_OF_WEEK);\n    }\n\n    /**\n     * 获取星期索引\n     * <p>注意：周日的Index才是1，周六为7</p>\n     *\n     * @param millis 毫秒时间戳\n     * @return 1...7\n     * @see Calendar#SUNDAY\n     * @see Calendar#MONDAY\n     * @see Calendar#TUESDAY\n     * @see Calendar#WEDNESDAY\n     * @see Calendar#THURSDAY\n     * @see Calendar#FRIDAY\n     * @see Calendar#SATURDAY\n     */\n    public static int getWeekIndex(final long millis) {\n        return getWeekIndex(millis2Date(millis));\n    }\n\n    /**\n     * 获取月份中的第几周\n     * <p>注意：国外周日才是新的一周的开始</p>\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 1...5\n     */\n    public static int getWeekOfMonth(final String time) {\n        return getWeekOfMonth(string2Date(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 获取月份中的第几周\n     * <p>注意：国外周日才是新的一周的开始</p>\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 1...5\n     */\n    public static int getWeekOfMonth(final String time, final DateFormat format) {\n        return getWeekOfMonth(string2Date(time, format));\n    }\n\n    /**\n     * 获取月份中的第几周\n     * <p>注意：国外周日才是新的一周的开始</p>\n     *\n     * @param date Date类型时间\n     * @return 1...5\n     */\n    public static int getWeekOfMonth(final Date date) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(date);\n        return cal.get(Calendar.WEEK_OF_MONTH);\n    }\n\n    /**\n     * 获取月份中的第几周\n     * <p>注意：国外周日才是新的一周的开始</p>\n     *\n     * @param millis 毫秒时间戳\n     * @return 1...5\n     */\n    public static int getWeekOfMonth(final long millis) {\n        return getWeekOfMonth(millis2Date(millis));\n    }\n\n    /**\n     * 获取年份中的第几周\n     * <p>注意：国外周日才是新的一周的开始</p>\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 1...54\n     */\n    public static int getWeekOfYear(final String time) {\n        return getWeekOfYear(string2Date(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 获取年份中的第几周\n     * <p>注意：国外周日才是新的一周的开始</p>\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 1...54\n     */\n    public static int getWeekOfYear(final String time, final DateFormat format) {\n        return getWeekOfYear(string2Date(time, format));\n    }\n\n    /**\n     * 获取年份中的第几周\n     * <p>注意：国外周日才是新的一周的开始</p>\n     *\n     * @param date Date类型时间\n     * @return 1...54\n     */\n    public static int getWeekOfYear(final Date date) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(date);\n        return cal.get(Calendar.WEEK_OF_YEAR);\n    }\n\n    /**\n     * 获取年份中的第几周\n     * <p>注意：国外周日才是新的一周的开始</p>\n     *\n     * @param millis 毫秒时间戳\n     * @return 1...54\n     */\n    public static int getWeekOfYear(final long millis) {\n        return getWeekOfYear(millis2Date(millis));\n    }\n\n    private static final String[] CHINESE_ZODIAC = {\"猴\", \"鸡\", \"狗\", \"猪\", \"鼠\", \"牛\", \"虎\", \"兔\", \"龙\", \"蛇\", \"马\", \"羊\"};\n\n    /**\n     * 获取生肖\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 生肖\n     */\n    public static String getChineseZodiac(final String time) {\n        return getChineseZodiac(string2Date(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 获取生肖\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 生肖\n     */\n    public static String getChineseZodiac(final String time, final DateFormat format) {\n        return getChineseZodiac(string2Date(time, format));\n    }\n\n    /**\n     * 获取生肖\n     *\n     * @param date Date类型时间\n     * @return 生肖\n     */\n    public static String getChineseZodiac(final Date date) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(date);\n        return CHINESE_ZODIAC[cal.get(Calendar.YEAR) % 12];\n    }\n\n    /**\n     * 获取生肖\n     *\n     * @param millis 毫秒时间戳\n     * @return 生肖\n     */\n    public static String getChineseZodiac(final long millis) {\n        return getChineseZodiac(millis2Date(millis));\n    }\n\n    /**\n     * 获取生肖\n     *\n     * @param year 年\n     * @return 生肖\n     */\n    public static String getChineseZodiac(final int year) {\n        return CHINESE_ZODIAC[year % 12];\n    }\n\n    private static final String[] ZODIAC = {\"水瓶座\", \"双鱼座\", \"白羊座\", \"金牛座\", \"双子座\", \"巨蟹座\", \"狮子座\", \"处女座\", \"天秤座\", \"天蝎座\", \"射手座\", \"魔羯座\"};\n    private static final int[] ZODIAC_FLAGS = {20, 19, 21, 21, 21, 22, 23, 23, 23, 24, 23, 22};\n\n    /**\n     * 获取星座\n     * <p>time格式为yyyy-MM-dd HH:mm:ss</p>\n     *\n     * @param time 时间字符串\n     * @return 生肖\n     */\n    public static String getZodiac(final String time) {\n        return getZodiac(string2Date(time, DEFAULT_FORMAT));\n    }\n\n    /**\n     * 获取星座\n     * <p>time格式为format</p>\n     *\n     * @param time   时间字符串\n     * @param format 时间格式\n     * @return 生肖\n     */\n    public static String getZodiac(final String time, final DateFormat format) {\n        return getZodiac(string2Date(time, format));\n    }\n\n    /**\n     * 获取星座\n     *\n     * @param date Date类型时间\n     * @return 星座\n     */\n    public static String getZodiac(final Date date) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(date);\n        int month = cal.get(Calendar.MONTH) + 1;\n        int day = cal.get(Calendar.DAY_OF_MONTH);\n        return getZodiac(month, day);\n    }\n\n    /**\n     * 获取星座\n     *\n     * @param millis 毫秒时间戳\n     * @return 星座\n     */\n    public static String getZodiac(final long millis) {\n        return getZodiac(millis2Date(millis));\n    }\n\n    /**\n     * 获取星座\n     *\n     * @param month 月\n     * @param day   日\n     * @return 星座\n     */\n    public static String getZodiac(final int month, final int day) {\n        return ZODIAC[day >= ZODIAC_FLAGS[month - 1]\n                ? month - 1\n                : (month + 10) % 12];\n    }\n\n    private static long timeSpan2Millis(final long timeSpan, @TimeConstants.Unit final int unit) {\n        return timeSpan * unit;\n    }\n\n    private static long millis2TimeSpan(final long millis, @TimeConstants.Unit final int unit) {\n        return millis / unit;\n    }\n\n    private static String millis2FitTimeSpan(long millis, int precision) {\n        if (millis < 0 || precision <= 0) return null;\n        precision = Math.min(precision, 5);\n        String[] units = {\"天\", \"小时\", \"分钟\", \"秒\", \"毫秒\"};\n        if (millis == 0) return 0 + units[precision - 1];\n        StringBuilder sb = new StringBuilder();\n        int[] unitLen = {86400000, 3600000, 60000, 1000, 1};\n        for (int i = 0; i < precision; i++) {\n            if (millis >= unitLen[i]) {\n                long mode = millis / unitLen[i];\n                millis -= mode * unitLen[i];\n                sb.append(mode).append(units[i]);\n            }\n        }\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/BaseView.java",
    "content": "package com.tophold.trade.view;\n\nimport android.content.Context;\nimport android.graphics.Paint;\nimport android.graphics.drawable.Drawable;\nimport android.support.annotation.ColorRes;\nimport android.support.annotation.DrawableRes;\nimport android.support.annotation.Nullable;\nimport android.support.annotation.StringRes;\nimport android.support.v4.content.ContextCompat;\nimport android.util.AttributeSet;\nimport android.view.View;\n\nimport static android.view.View.MeasureSpec.AT_MOST;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ： 20180404\n * 描 述 ：整个自定义view最基础的类，在这里做一些基础重复的操作。\n * ============================================================\n */\npublic abstract class BaseView extends View {\n\n    protected String TAG;\n\n    protected Context mContext;\n\n    //长按阀值，默认多长时间算长按（ms）。不再设置为final,允许用户修改。\n    protected long def_longpress_length = 700;\n    //单击阀值\n    protected long def_clickpress_length = 100;\n    //移动阀值。手指移动多远算移动的阀值（单位：sp）\n    protected long def_pull_length = 5;\n    //onFling的阀值\n    protected float def_onfling = 5;\n\n    //控件默认宽高。当控件的宽高设置为wrap_content时会采用该参数进行默认的设置（单位：sp）。\n    //不允许用户修改，想要修改宽高，使用mWidth、mBaseHeight。\n    protected final float DEF_WIDTH = 650;\n    protected final float DEF_HIGHT = 400;\n\n    //测量的控件宽高，会在onMeasure中进行测量。\n    protected int mBaseWidth;\n    protected int mBaseHeight;\n\n\n    public BaseView(Context context) {\n        this(context, null);\n    }\n\n    public BaseView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        TAG = this.getClass().getSimpleName();\n        mContext = context;\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);\n        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);\n        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);\n        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);\n        if (widthSpecMode == AT_MOST && heightSpecMode == AT_MOST) {\n            setMeasuredDimension((int) DEF_WIDTH, (int) DEF_HIGHT);\n        } else if (widthSpecMode == AT_MOST) {\n            setMeasuredDimension((int) DEF_WIDTH, heightSpecSize);\n        } else if (heightSpecMode == AT_MOST) {\n            setMeasuredDimension(widthSpecSize, (int) DEF_HIGHT);\n        } else {\n            setMeasuredDimension(widthSpecSize, heightSpecSize);\n        }\n        mBaseWidth = getMeasuredWidth();\n        mBaseHeight = getMeasuredHeight();\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n        super.onLayout(changed, left, top, right, bottom);\n    }\n\n    /**\n     * 根据颜色id获取颜色\n     *\n     * @param colorId\n     * @return\n     */\n    protected int getColor(@ColorRes int colorId) {\n        return ContextCompat.getColor(mContext, colorId);\n    }\n\n    protected String getString(@StringRes int stringId) {\n        return getResources().getString(stringId);\n    }\n\n    protected Drawable getDrawable(@DrawableRes int drawableId) {\n        return ContextCompat.getDrawable(mContext, drawableId);\n    }\n\n    protected int dp2px(float dp) {\n        final float scale = mContext.getResources().getDisplayMetrics().density;\n        return (int) (dp * scale + 0.5f);\n    }\n\n    protected int sp2px(float sp) {\n        final float fontScale = mContext.getResources().getDisplayMetrics().scaledDensity;\n        return (int) (sp * fontScale + 0.5f);\n    }\n\n    /**\n     * 测量指定画笔的文字的高度\n     *\n     * @param fontSize\n     * @param paint\n     * @return\n     */\n    protected float getFontHeight(float fontSize, Paint paint) {\n        paint.setTextSize(fontSize);\n        Paint.FontMetrics fm = paint.getFontMetrics();\n        return (float) (Math.ceil(fm.descent - fm.top) + 2f);\n    }\n\n\n    //----------------------对用户暴露可以修改的参数------------------\n\n    public long getDef_longpress_length() {\n        return def_longpress_length;\n    }\n\n    public void setDef_longpress_length(long def_longpress_length) {\n        this.def_longpress_length = def_longpress_length;\n    }\n\n    public long getDef_clickpress_length() {\n        return def_clickpress_length;\n    }\n\n    public void setDef_clickpress_length(long def_clickpress_length) {\n        this.def_clickpress_length = def_clickpress_length;\n    }\n\n    public long getDef_pull_length() {\n        return def_pull_length;\n    }\n\n    public void setDef_pull_length(long def_pull_length) {\n        this.def_pull_length = def_pull_length;\n    }\n\n    public float getDEF_WIDTH() {\n        return DEF_WIDTH;\n    }\n\n    public float getDEF_HIGHT() {\n        return DEF_HIGHT;\n    }\n\n    public int getBaseWidth() {\n        return mBaseWidth;\n    }\n\n    public void setBaseWidth(int baseWidth) {\n        mBaseWidth = baseWidth;\n    }\n\n    public int getBaseHeight() {\n        return mBaseHeight;\n    }\n\n    public void setBaseHeight(int baseHeight) {\n        mBaseHeight = baseHeight;\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/fund/FundMode.java",
    "content": "package com.tophold.trade.view.fund;\n\n\nimport com.tophold.trade.utils.RegxUtils;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/10/25 14:50\n * 描 述 ：\n * ============================================================\n **/\npublic class FundMode {\n    //x轴原始时间数据，ms\n    public long datetime;\n    //y轴的原始数据\n    public String originDataY;\n    //y轴的转换后的数据\n    public float dataY;\n\n    //在自定义view:FundView中的位置坐标\n    public float floatX;\n    public float floatY;\n\n    public FundMode(long timestamp, String actual) {\n        this.datetime = timestamp;\n        this.originDataY = actual;\n        this.dataY = RegxUtils.getPureDouble(originDataY);//提取后的Y周的值\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/fund/FundView.java",
    "content": "package com.tophold.trade.view.fund;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.DashPathEffect;\nimport android.graphics.Paint;\nimport android.graphics.Path;\nimport android.graphics.PathEffect;\nimport android.support.annotation.Nullable;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.MotionEvent;\n\nimport java.text.SimpleDateFormat;\nimport java.util.List;\n\nimport com.tophold.trade.R;\nimport com.tophold.trade.view.BaseView;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/10/25 14:47，update:2018/04/05\n * 描 述 ：蚂蚁财富基金收益折线图。\n * 想要定制：哪些字段可以修改？哪些字段不能修改？\n * 可以修改：各种画笔的状态（颜色、样式、粗细、文字大小）、边界padding、宽高等；\n * 不可以修改：计算出来的最大值最小值、boolean类型的临时状态、长按所赋的值、单元大小等\n * （随便修改不建议修改的字段可能会发生不可预料的问题你，但是所有字段都会暴露出去（尽量），给更大的灵活性去定制）。\n * 注意：对于Paint的子属性请直接调用Piant然后再进行设置，\n * 不要（程序已经限制，因为会和外部调用Paint去设置属性混乱）使用该内部的Paint的设置子属性的方法。\n * ============================================================\n **/\npublic class FundView extends BaseView {\n\n    //数据源\n    List<FundMode> mFundModeList;\n\n    //上下左右padding,允许修改\n    protected float mBasePaddingTop = 100;\n    protected float mBasePaddingBottom = 70;\n    protected float mBasePaddingLeft = 50;\n    protected float mBasePaddingRight = 50;\n\n    //Y轴对应的最大值和最小值,注意，这里存的是对象。原则上不允许修改。\n    protected FundMode mMinFundMode;\n    protected FundMode mMaxFundMode;\n\n    //X、Y轴每一个data对应的大小。原则上不允许修改。\n    protected float mPerX;\n    protected float mPerY;\n\n    //正在加载中,允许修改\n    protected Paint mLoadingPaint;\n    protected float mLoadingTextSize = 20;\n    protected String mLoadingText = \"数据加载，请稍后\";\n    //原则上不允许修改。\n    protected boolean mDrawLoadingPaint = true;\n\n\n    //外围X、Y轴线文字。允许修改。\n    protected Paint mXYPaint;\n    //x、y轴指示文字字体的大小\n    protected float mXYTextSize = 14;\n    //左侧文字距离左边线线的距离\n    protected float mLeftTxtPadding = 16;\n    //底部文字距离底部线的距离\n    protected float mBottomTxtPadding = 20;\n\n\n    //内部X轴虚线。允许修改。\n    protected Paint mInnerXPaint;\n    protected float mInnerXStrokeWidth = 1;\n\n    //折线。允许修改。\n    protected Paint mBrokenPaint;\n    //单位：sp.。允许修改。\n    protected float mBrokenStrokeWidth = 1;\n\n    //长按的十字线，允许修改。\n    protected Paint mLongPressPaint;\n    //原则上不允许修改。\n    protected boolean mDrawLongPressPaint = false;\n    //长按处理,原则上不允许修改。\n    protected long mPressTime;\n    protected float mPressX;\n    protected float mPressY;\n\n    //最上面默认显示累计收益金额，允许修改。\n    protected Paint mDefAllIncomePaint;\n    protected float mDefAllIncomeTextSize = 20;\n\n\n    //长按情况下x轴和y轴要显示的文字,允许修改。\n    protected Paint mLongPressTxtPaint;\n    protected float mLongPressTextSize = 20;\n\n    public FundView(Context context) {\n        this(context, null);\n    }\n\n    public FundView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public FundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initAttrs();\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n        super.onLayout(changed, left, top, right, bottom);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n\n        //setDefAttrs();\n\n        //默认加载loading界面\n        showLoadingPaint(canvas);\n        if (mFundModeList == null || mFundModeList.size() == 0) return;\n\n        //加载三个核心Paint\n        drawInnerXPaint(canvas);\n        drawBrokenPaint(canvas);\n        drawXYPaint(canvas);\n\n        drawTopTxtPaint(canvas);\n\n        drawLongPress(canvas);\n    }\n\n    @Override\n    public boolean onTouchEvent(MotionEvent event) {\n        switch (event.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                mPressTime = event.getDownTime();\n                break;\n            case MotionEvent.ACTION_MOVE:\n                if (event.getEventTime() - mPressTime > def_longpress_length) {\n                    Log.d(TAG, \"onTouchEvent: 长按了。。。\");\n                    mPressX = event.getX();\n                    mPressY = event.getY();\n                    //处理长按后的逻辑\n                    showLongPressView();\n                }\n                break;\n            case MotionEvent.ACTION_UP:\n                //处理松手后的逻辑\n                hiddenLongPressView();\n                break;\n            default:\n                break;\n        }\n\n        return true;\n    }\n\n    private void initAttrs() {\n        initLoadingPaint();\n        initInnerXPaint();\n        initXYPaint();\n        initBrokenPaint();\n        initLongPressPaint();\n        initTopTxt();\n    }\n\n    private void initLoadingPaint() {\n        mLoadingPaint = new Paint();\n        mLoadingPaint.setColor(getColor(R.color.color_fundView_xyTxtColor));\n        mLoadingPaint.setTextSize(mLoadingTextSize);\n        mLoadingPaint.setAntiAlias(true);\n    }\n\n    //初始化绘制虚线的画笔\n    private void initInnerXPaint() {\n        mInnerXPaint = new Paint();\n        mInnerXPaint.setColor(getColor(R.color.color_fundView_xLineColor));\n        mInnerXPaint.setStrokeWidth(mInnerXStrokeWidth);\n        mInnerXPaint.setStyle(Paint.Style.STROKE);\n        setLayerType(LAYER_TYPE_SOFTWARE, null);//禁用硬件加速\n        PathEffect effects = new DashPathEffect(new float[]{5, 5, 5, 5}, 1);\n        mInnerXPaint.setPathEffect(effects);\n    }\n\n    private void initXYPaint() {\n        mXYPaint = new Paint();\n        mXYPaint.setColor(getColor(R.color.color_fundView_xyTxtColor));\n        mXYPaint.setTextSize(mXYTextSize);\n        mXYPaint.setAntiAlias(true);\n    }\n\n    private void initBrokenPaint() {\n        mBrokenPaint = new Paint();\n        mBrokenPaint.setColor(getColor(R.color.color_fundView_brokenLineColor));\n        mBrokenPaint.setStyle(Paint.Style.STROKE);\n        mBrokenPaint.setAntiAlias(true);\n        mBrokenPaint.setStrokeWidth(mBrokenStrokeWidth);\n    }\n\n    private void initLongPressPaint() {\n        mLongPressPaint = new Paint();\n        mLongPressPaint.setColor(getColor(R.color.color_fundView_longPressLineColor));\n        mLongPressPaint.setStyle(Paint.Style.FILL);\n        mLongPressPaint.setAntiAlias(true);\n        mLongPressPaint.setTextSize(mLongPressTextSize);\n    }\n\n    //折线上面显示文字信息\n    private void initTopTxt() {\n        mDefAllIncomePaint = new Paint();\n        mDefAllIncomePaint.setColor(getColor(R.color.color_fundView_defIncomeTxt));\n        mDefAllIncomePaint.setTextSize(mLongPressTextSize);\n        mDefAllIncomePaint.setAntiAlias(true);\n\n        mLongPressTxtPaint = new Paint();\n        mLongPressTxtPaint.setColor(getColor(R.color.color_fundView_longPressLineColor));\n        mLongPressTxtPaint.setTextSize(mLongPressTextSize);\n        mLongPressTxtPaint.setAntiAlias(true);\n    }\n\n    /**\n     * 将画笔使用的属性在这里设置。\n     * 主要是为了覆盖用户动态设置的属性，\n     * 因为在构造方法中设置的会无效（用户设置的在构造方法之后）。\n     * 注意：这个方法不能使用，因为会覆盖Paint内部的设置属性的方法\n     */\n    @Deprecated\n    private void setDefAttrs() {\n        mLoadingPaint.setTextSize(mLoadingTextSize);\n        mInnerXPaint.setStrokeWidth(mInnerXStrokeWidth);\n        mXYPaint.setTextSize(mXYTextSize);\n        mBrokenPaint.setStrokeWidth(mBrokenStrokeWidth);\n        mLongPressPaint.setTextSize(mLongPressTextSize);\n        mDefAllIncomePaint.setTextSize(mLongPressTextSize);\n        mLongPressTxtPaint.setTextSize(mLongPressTextSize);\n    }\n\n    private void showLoadingPaint(Canvas canvas) {\n        if (!mDrawLoadingPaint) return;\n        //这里特别注意，x轴的起始点要减去文字宽度的一半\n        canvas.drawText(mLoadingText, mBaseWidth / 2 - mLoadingPaint.measureText(mLoadingText) / 2, mBaseHeight / 2, mLoadingPaint);\n    }\n\n    private void drawInnerXPaint(Canvas canvas) {\n        //画5条横轴的虚线\n        //首先确定最大值和最小值的位置\n        float perHight = (mBaseHeight - mBasePaddingBottom - mBasePaddingTop) / 4;\n\n        canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop,\n                mBaseWidth - mBasePaddingRight, mBasePaddingTop, mInnerXPaint);//最上面的那一条\n\n        canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 1,\n                mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 1, mInnerXPaint);//2\n\n        canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 2,\n                mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 2, mInnerXPaint);//3\n\n        canvas.drawLine(0 + mBasePaddingLeft, mBasePaddingTop + perHight * 3,\n                mBaseWidth - mBasePaddingRight, mBasePaddingTop + perHight * 3, mInnerXPaint);//4\n\n        canvas.drawLine(0 + mBasePaddingLeft, mBaseHeight - mBasePaddingBottom,\n                mBaseWidth - mBasePaddingRight, mBaseHeight - mBasePaddingBottom, mInnerXPaint);//最下面的那一条\n\n    }\n\n    private void drawBrokenPaint(Canvas canvas) {\n        //先画第一个点\n        FundMode fundMode = mFundModeList.get(0);\n        Path path = new Path();\n        //这里需要说明一下，x轴的起始点，其实需要加上mPerX，但是加上之后不是从起始位置开始，不好看。\n        // 同理，for循环内x轴其实需要(i+1)。现在这样处理，最后会留一点空隙，其实挺好看的。\n        float floatY = mBaseHeight - mBasePaddingBottom - mPerY * (fundMode.dataY - mMinFundMode.dataY);\n        fundMode.floatX = mBasePaddingLeft;\n        fundMode.floatY = floatY;\n        path.moveTo(mBasePaddingLeft, floatY);\n        for (int i = 1; i < mFundModeList.size(); i++) {\n            FundMode fm = mFundModeList.get(i);\n            float floatX2 = mBasePaddingLeft + mPerX * i;\n            float floatY2 = mBaseHeight - mBasePaddingBottom - mPerY * (fm.dataY - mMinFundMode.dataY);\n            fm.floatX = floatX2;\n            fm.floatY = floatY2;\n            path.lineTo(floatX2, floatY2);\n            //Log.e(TAG, \"drawBrokenPaint: \" + mBasePaddingLeft + mPerX * i + \"-----\" + (mBaseHeight - mClosePerY * (mFundModeList.get(i).dataY - mMinFundMode.dataY) - mBasePaddingBottom));\n        }\n\n        canvas.drawPath(path, mBrokenPaint);\n\n\n    }\n\n    private void drawXYPaint(Canvas canvas) {\n        //先处理y轴方向文字\n        drawYPaint(canvas);\n\n        //处理x轴方向文字\n        drawXPaint(canvas);\n    }\n\n    private void drawTopTxtPaint(Canvas canvas) {\n        //先画默认情况下的top文字\n        drawDefTopTxtpaint(canvas);\n        //按下的文字信息在按下之后处理，see:drawLongPress(Canvas canvas)\n    }\n\n    /**\n     * 这里处理画十字的逻辑:这里的十字不是手指按下的位置，这样没有意义。\n     * 而是当前按下的距离x轴最近的时间（注意：并不一定按下对应的x轴就是有时间的，如果没有取最近的）。\n     * 当取到x轴的值，之后算出来对应的y轴的值，这个才是十字对应的位置坐标。\n     * 如何获取x轴最近的时间？我们可以在FundMode中定义x\\y的位置参数，遍历对比找到最小即可。\n     * (see: drawBrokenPaint(canvas);)\n     *\n     * @param canvas\n     */\n    private void drawLongPress(Canvas canvas) {\n        if (!mDrawLongPressPaint) return;\n\n        //获取距离最近按下的位置的model\n        float pressX = mPressX;\n        //循环遍历，找到距离最短的x轴的mode\n        FundMode finalFundMode = mFundModeList.get(0);\n        float minXLen = Integer.MAX_VALUE;\n        for (int i = 0; i < mFundModeList.size(); i++) {\n            FundMode currFunMode = mFundModeList.get(i);\n            float abs = Math.abs(pressX - currFunMode.floatX);\n            if (abs < minXLen) {\n                finalFundMode = currFunMode;\n                minXLen = abs;\n            }\n        }\n\n        //x\n        canvas.drawLine(mBasePaddingLeft, finalFundMode.floatY, mBaseWidth - mBasePaddingRight, finalFundMode.floatY, mLongPressPaint);\n        //y\n        canvas.drawLine(finalFundMode.floatX, mBasePaddingTop, finalFundMode.floatX, mBaseHeight - mBasePaddingBottom, mLongPressPaint);\n\n        //开始处理按下之后top的文字信息\n        //先画背景\n        float hight = mBasePaddingTop - 30;\n        Paint bgColor = new Paint(Paint.ANTI_ALIAS_FLAG);\n        bgColor.setColor(getColor(R.color.color_fundView_pressIncomeTxtBg));\n        canvas.drawRect(0, 0, mBaseWidth, hight, bgColor);\n\n        //开始画按下之后左边的日期文字\n        Paint timePaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        timePaint.setTextSize(mLongPressTextSize);\n        timePaint.setColor(getColor(R.color.color_fundView_xyTxtColor));\n        canvas.drawText(processDateTime(finalFundMode.datetime) + \"\",\n                10, hight / 2 + getFontHeight(mLongPressTextSize, timePaint) / 2, timePaint);\n\n        //右边红色收益文字\n        canvas.drawText(finalFundMode.dataY + \"\",\n                mBaseWidth - mBasePaddingRight - mLongPressPaint.measureText(finalFundMode.dataY + \"\"),\n                hight / 2 + getFontHeight(mLongPressTextSize, timePaint) / 2, mLongPressPaint);\n\n        //右边的左边的提示文字\n        Paint hintPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        hintPaint.setTextSize(mLongPressTextSize);\n        hintPaint.setColor(getColor(R.color.color_fundView_xyTxtColor));\n        canvas.drawText(getString(R.string.string_fundView_pressHintTxt),\n                mBaseWidth - mBasePaddingRight - mLongPressPaint.measureText(finalFundMode.dataY + \"\")\n                        - hintPaint.measureText(getString(R.string.string_fundView_pressHintTxt)),\n                hight / 2 + getFontHeight(mLongPressTextSize, timePaint) / 2, hintPaint);\n\n\n    }\n\n    //找到最大时间、最小时间和中间时间显示即可\n    private void drawXPaint(Canvas canvas) {\n        long beginTime = mFundModeList.get(0).datetime;\n        long midTime = mFundModeList.get((mFundModeList.size() - 1) / 2).datetime;\n        long endTime = mFundModeList.get(mFundModeList.size() - 1).datetime;\n        String bengin = processDateTime(beginTime);\n        String mid = processDateTime(midTime);\n        String end = processDateTime(endTime);\n\n        //x轴文字的高度\n        float hight = mBaseHeight - mBasePaddingBottom + mBottomTxtPadding;\n\n        canvas.drawText(bengin,\n                mBasePaddingLeft,\n                hight, mXYPaint);\n\n        canvas.drawText(mid,\n                mBasePaddingLeft + (mBaseWidth - mBasePaddingLeft - mBasePaddingRight) / 2,\n                hight, mXYPaint);\n\n        canvas.drawText(end,\n                mBaseWidth - mBasePaddingRight - mXYPaint.measureText(end),\n                hight, mXYPaint);//特别注意x轴的处理：- mXYPaint.measureText(end)\n\n    }\n\n    private void drawYPaint(Canvas canvas) {\n        //现将最小值、最大值画好\n        //draw min\n        float txtWigth = mXYPaint.measureText(mMinFundMode.originDataY) + mLeftTxtPadding;\n        canvas.drawText(mMinFundMode.originDataY + \"\",\n                mBasePaddingLeft - txtWigth,\n                mBaseHeight - mBasePaddingBottom, mXYPaint);\n        //draw max\n        canvas.drawText(mMaxFundMode.dataY + \"\",\n                mBasePaddingLeft - txtWigth,\n                mBasePaddingTop, mXYPaint);\n        //因为横线是均分的，所以只要取到最大值最小值的差值，均分即可。\n        float perYValues = (mMaxFundMode.dataY - mMinFundMode.dataY) / 4;\n        float perYWidth = (mBaseHeight - mBasePaddingBottom - mBasePaddingTop) / 4;\n        //从下到上依次画\n        for (int i = 1; i <= 3; i++) {\n            canvas.drawText(mMinFundMode.dataY + perYValues * i + \"\",\n                    mBasePaddingLeft - txtWigth,\n                    mBaseHeight - mBasePaddingBottom - perYWidth * i, mXYPaint);\n        }\n    }\n\n    private void drawDefTopTxtpaint(Canvas canvas) {\n        //画默认情况下前面的蓝色小圆点\n        Paint buleDotPaint = new Paint();\n        buleDotPaint.setColor(getColor(R.color.color_fundView_brokenLineColor));\n        buleDotPaint.setAntiAlias(true);\n        float r = 6;\n        buleDotPaint.setStyle(Paint.Style.FILL);\n        canvas.drawCircle(mBasePaddingLeft + r / 2, mBasePaddingTop / 2 + r, r, buleDotPaint);\n\n        float txtHight = getFontHeight(mDefAllIncomeTextSize, mDefAllIncomePaint);\n\n        //先画hint文字\n        Paint hintPaint = new Paint();\n        hintPaint.setColor(getColor(R.color.color_fundView_xyTxtColor));\n        hintPaint.setAntiAlias(true);\n        hintPaint.setTextSize(mDefAllIncomeTextSize);\n        String hintTxt = getString(R.string.string_fundView_defHintTxt);\n        canvas.drawText(hintTxt, mBasePaddingLeft + r + 10, mBasePaddingTop / 2 + txtHight / 2,\n                mDefAllIncomePaint);\n\n\n        if (mFundModeList == null || mFundModeList.isEmpty()) return;\n        canvas.drawText(mFundModeList.get(mFundModeList.size() - 1).dataY + \"\",\n                mBasePaddingLeft + r + 10 + hintPaint.measureText(getString(R.string.string_fundView_defHintTxt)) + 5,\n                mBasePaddingTop / 2 + txtHight / 2, mDefAllIncomePaint);\n    }\n\n    private void showLongPressView() {\n        mDrawLongPressPaint = true;\n        invalidate();\n    }\n\n    private void hiddenLongPressView() {\n        //实现蚂蚁金服延迟消失十字线\n        postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                mDrawLongPressPaint = false;\n                invalidate();\n            }\n        }, 1000);\n    }\n\n    // 只需要把画笔颜色置为透明即可\n    private void hiddenLoadingPaint() {\n        mLoadingPaint.setColor(0x00000000);\n        mDrawLoadingPaint = false;\n    }\n\n    private String processDateTime(long beginTime) {\n        SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd\");\n        return sdf.format(beginTime);\n    }\n\n    public float getFontHeight(float fontSize, Paint paint) {\n        paint.setTextSize(fontSize);\n        Paint.FontMetrics fm = paint.getFontMetrics();\n        return (float) (Math.ceil(fm.descent - fm.top) + 2);\n    }\n\n    /**\n     * 程序入口，设置数据\n     */\n    public void setDataList(List<FundMode> fundModeList) {\n        if (fundModeList == null || fundModeList.size() == 0) return;\n        this.mFundModeList = fundModeList;\n\n        //开始获取最大值最小值；单个数据尺寸等\n        mMinFundMode = mFundModeList.get(0);\n        mMaxFundMode = mFundModeList.get(0);\n        for (FundMode fundMode : mFundModeList) {\n            if (fundMode.dataY < mMinFundMode.dataY) {\n                mMinFundMode = fundMode;\n            }\n            if (fundMode.dataY > mMaxFundMode.dataY) {\n                mMaxFundMode = fundMode;\n            }\n        }\n        //获取单个数据X/y轴的大小\n        mPerX = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight) / mFundModeList.size();\n        mPerY = ((mBaseHeight - mBasePaddingTop - mBasePaddingBottom) / (mMaxFundMode.dataY - mMinFundMode.dataY));\n        Log.e(TAG, \"setDataList: \" + mMinFundMode + \",\" + mMaxFundMode + \"...\" + mPerX + \",\" + mPerY);\n\n        //数据过来，隐藏加载更多\n        hiddenLoadingPaint();\n\n        //刷新界面\n        invalidate();\n    }\n\n\n    //-----------------------对开发者暴露可以修改的参数-------\n\n\n    public List<FundMode> getFundModeList() {\n        return mFundModeList;\n    }\n\n    public FundView setFundModeList(List<FundMode> fundModeList) {\n        mFundModeList = fundModeList;\n        return this;\n    }\n\n    public float getBasePaddingTop() {\n        return mBasePaddingTop;\n    }\n\n    public FundView setBasePaddingTop(float basePaddingTop) {\n        mBasePaddingTop = basePaddingTop;\n        return this;\n    }\n\n    public float getBasePaddingBottom() {\n        return mBasePaddingBottom;\n    }\n\n    public FundView setBasePaddingBottom(float basePaddingBottom) {\n        mBasePaddingBottom = basePaddingBottom;\n        return this;\n    }\n\n    public float getBasePaddingLeft() {\n        return mBasePaddingLeft;\n    }\n\n    public FundView setBasePaddingLeft(float basePaddingLeft) {\n        mBasePaddingLeft = basePaddingLeft;\n        return this;\n    }\n\n    public float getBasePaddingRight() {\n        return mBasePaddingRight;\n    }\n\n    public FundView setBasePaddingRight(float basePaddingRight) {\n        mBasePaddingRight = basePaddingRight;\n        return this;\n    }\n\n    public FundMode getMinFundMode() {\n        return mMinFundMode;\n    }\n\n    public FundView setMinFundMode(FundMode minFundMode) {\n        mMinFundMode = minFundMode;\n        return this;\n    }\n\n    public FundMode getMaxFundMode() {\n        return mMaxFundMode;\n    }\n\n    public FundView setMaxFundMode(FundMode maxFundMode) {\n        mMaxFundMode = maxFundMode;\n        return this;\n    }\n\n    public float getPerX() {\n        return mPerX;\n    }\n\n    public FundView setPerX(float perX) {\n        mPerX = perX;\n        return this;\n    }\n\n    public float getPerY() {\n        return mPerY;\n    }\n\n    public FundView setPerY(float perY) {\n        mPerY = perY;\n        return this;\n    }\n\n    public Paint getLoadingPaint() {\n        return mLoadingPaint;\n    }\n\n    public FundView setLoadingPaint(Paint loadingPaint) {\n        mLoadingPaint = loadingPaint;\n        return this;\n    }\n\n    public float getLoadingTextSize() {\n        return mLoadingTextSize;\n    }\n\n    private FundView setLoadingTextSize(float loadingTextSize) {\n        mLoadingTextSize = loadingTextSize;\n        return this;\n    }\n\n    public String getLoadingText() {\n        return mLoadingText;\n    }\n\n    public FundView setLoadingText(String loadingText) {\n        mLoadingText = loadingText;\n        return this;\n    }\n\n    public boolean isDrawLoadingPaint() {\n        return mDrawLoadingPaint;\n    }\n\n    public FundView setDrawLoadingPaint(boolean drawLoadingPaint) {\n        mDrawLoadingPaint = drawLoadingPaint;\n        return this;\n    }\n\n    public Paint getXYPaint() {\n        return mXYPaint;\n    }\n\n    public FundView setXYPaint(Paint XYPaint) {\n        mXYPaint = XYPaint;\n        return this;\n    }\n\n    public float getXYTextSize() {\n        return mXYTextSize;\n    }\n\n    private FundView setXYTextSize(float XYTextSize) {\n        mXYTextSize = XYTextSize;\n        return this;\n    }\n\n    public float getLeftTxtPadding() {\n        return mLeftTxtPadding;\n    }\n\n    public FundView setLeftTxtPadding(float leftTxtPadding) {\n        mLeftTxtPadding = leftTxtPadding;\n        return this;\n    }\n\n    public float getBottomTxtPadding() {\n        return mBottomTxtPadding;\n    }\n\n    public FundView setBottomTxtPadding(float bottomTxtPadding) {\n        mBottomTxtPadding = bottomTxtPadding;\n        return this;\n    }\n\n    public Paint getInnerXPaint() {\n        return mInnerXPaint;\n    }\n\n    public FundView setInnerXPaint(Paint innerXPaint) {\n        mInnerXPaint = innerXPaint;\n        return this;\n    }\n\n    public float getInnerXStrokeWidth() {\n        return mInnerXStrokeWidth;\n    }\n\n    private FundView setInnerXStrokeWidth(float innerXStrokeWidth) {\n        mInnerXStrokeWidth = innerXStrokeWidth;\n        return this;\n    }\n\n    public Paint getBrokenPaint() {\n        return mBrokenPaint;\n    }\n\n    public FundView setBrokenPaint(Paint brokenPaint) {\n        mBrokenPaint = brokenPaint;\n        return this;\n    }\n\n    public float getBrokenStrokeWidth() {\n        return mBrokenStrokeWidth;\n    }\n\n    private FundView setBrokenStrokeWidth(float brokenStrokeWidth) {\n        mBrokenStrokeWidth = brokenStrokeWidth;\n        return this;\n    }\n\n    public Paint getLongPressPaint() {\n        return mLongPressPaint;\n    }\n\n    public FundView setLongPressPaint(Paint longPressPaint) {\n        mLongPressPaint = longPressPaint;\n        return this;\n    }\n\n    public boolean isDrawLongPressPaint() {\n        return mDrawLongPressPaint;\n    }\n\n    public FundView setDrawLongPressPaint(boolean drawLongPressPaint) {\n        mDrawLongPressPaint = drawLongPressPaint;\n        return this;\n    }\n\n    public long getPressTime() {\n        return mPressTime;\n    }\n\n    public FundView setPressTime(long pressTime) {\n        mPressTime = pressTime;\n        return this;\n    }\n\n    public float getPressX() {\n        return mPressX;\n    }\n\n    public FundView setPressX(float pressX) {\n        mPressX = pressX;\n        return this;\n    }\n\n    public float getPressY() {\n        return mPressY;\n    }\n\n    public FundView setPressY(float pressY) {\n        mPressY = pressY;\n        return this;\n    }\n\n    public Paint getDefAllIncomePaint() {\n        return mDefAllIncomePaint;\n    }\n\n    public FundView setDefAllIncomePaint(Paint defAllIncomePaint) {\n        mDefAllIncomePaint = defAllIncomePaint;\n        return this;\n    }\n\n    public float getDefAllIncomeTextSize() {\n        return mDefAllIncomeTextSize;\n    }\n\n    public FundView setDefAllIncomeTextSize(float defAllIncomeTextSize) {\n        mDefAllIncomeTextSize = defAllIncomeTextSize;\n        return this;\n    }\n\n    public Paint getLongPressTxtPaint() {\n        return mLongPressTxtPaint;\n    }\n\n    public FundView setLongPressTxtPaint(Paint longPressTxtPaint) {\n        mLongPressTxtPaint = longPressTxtPaint;\n        return this;\n    }\n\n    public float getLongPressTextSize() {\n        return mLongPressTextSize;\n    }\n\n    private FundView setLongPressTextSize(float longPressTextSize) {\n        mLongPressTextSize = longPressTextSize;\n        return this;\n    }\n}\n\n\n\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/FinancialAlgorithm.java",
    "content": "package com.tophold.trade.view.kview;\n\nimport android.util.Log;\n\nimport java.util.List;\n\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/12/18 11:24\n * 描 述 ：所有金融相关算法全部在这里。算法参考【资料】包中的：常用股票指标计算公式及简单应用.pdf\n * ============================================================\n **/\n// TODO: 2017/12/18 这里的算法需要核实！包括异常情况的处理和边界的处理是否合适。\npublic class FinancialAlgorithm {\n    final static String TAG = FinancialAlgorithm.class.getSimpleName();\n\n    public static void calculateKDJ(List<Quotes> quotesList) {\n        calculateKDJ(quotesList, 9, 3, 3);\n    }\n\n    /**\n     * 【该算法核对过，但是和线上的APP有细微的差距，不知道是否有错！】计算数据集合的kdj。\n     *\n     * @param quotesList 对应的数据集合\n     * @param kPeriod    k所对应的周期，可以是：分钟、小时、天等\n     * @param dPeriod    d所对应的周期，可以是：分钟、小时、天等\n     * @param jPeriod    j所对应的周期，可以是：分钟、小时、天等\n     */\n    public static void calculateKDJ(List<Quotes> quotesList, int kPeriod, int dPeriod, int jPeriod) {\n        //容错\n        if (quotesList == null || quotesList.isEmpty()) return;\n        if (kPeriod <= 0) kPeriod = 9;\n        if (dPeriod <= 0) dPeriod = 3;\n        if (jPeriod <= 0) jPeriod = 3;\n\n        //转换程序员的序号\n        kPeriod--;\n        dPeriod--;\n        jPeriod--;\n        double kRsv = 0;\n        //double dRsv=0;\n        double k = 0;\n        double d = 0;\n        double j = 0;\n        for (int i = 0; i < quotesList.size(); i++) {\n            Quotes quotes = quotesList.get(i);\n\n            //计算k\n            if (i < kPeriod) {\n                k = 50;\n            } else {\n                double c = 0;\n                double l = 0;\n                double h = 0;\n                double tempL = Integer.MAX_VALUE;\n                double tempH = Integer.MIN_VALUE;\n                for (int i1 = i - kPeriod; i1 <= i; i1++) {\n                    Quotes kQuotes = quotesList.get(i1);\n                    if (kQuotes.c < tempL) {\n                        tempL = kQuotes.c;\n                        l = tempL;\n                    }\n                    if (kQuotes.c > tempH) {\n                        tempH = kQuotes.c;\n                        h = tempH;\n                    }\n                    if (i1 == i) {\n                        c = kQuotes.c;\n                    }\n                }\n                kRsv = (c - l) / (h - l) * 100;\n                k = 2 / 3.0 * k + 1 / 3.0 * kRsv;\n            }\n            quotes.k = k;\n\n            //计算d\n            if (i < dPeriod) {\n                d = 50;\n            } else {\n                d = 2 / 3.0 * d + 1 / 3.0 * quotes.k;\n            }\n            quotes.d = d;\n\n            //计算j\n            j = 3 * quotes.k - 2 * quotes.d;\n            quotes.j = j;\n\n            //计算结束\n            //打印测试\n            //Log.e(TAG, \"calculateKDJ: k:\" + quotes.k + \",d:\" + quotes.d + \",j:\" + quotes.j);\n        }\n    }\n\n    public static void calculateMACD(List<Quotes> quotesList) {\n        calculateMACD(quotesList, 12, 26, 9);\n    }\n\n    /**\n     * MACD(x,y,z)，一般取MACD(12,26,9)。\n     * MACD(x,y,z)，x、y为平滑指数。z暂时不知道用处（不影响算法）。\n     * `EMAx=((x-1)/(x+1.0)*前一日EMA)+2.0/(x+1)*今日收盘价`;其中第一日的EMA是当日的收盘价。\n     * `EMA12=(11/13.0)*[前一日EMA12]+2.0/13*[今日quotes.c]`\n     * `EMA26=(25/27.0)*[前一日EMA26]+2.0/27*[今日quotes.c]`\n     * DIF:`DIF=EMA12-EMA26`\n     * DEA:`DEA=8/10.0*(前一日的DEA)+2/10.0*今日DIF`\n     * MACD:`2*(DIF-DEA)`\n     *\n     * @param quotesList 数据集合\n     * @param d1         平滑指数，一般为12\n     * @param d2         平滑指数，一般为26\n     * @param z          暂时未知\n     */\n    public static void calculateMACD(List<Quotes> quotesList, int d1, int d2, int z) {\n        //容错\n        if (quotesList == null || quotesList.isEmpty()) return;\n\n        double ema12 = 0;\n        double ema26 = 0;\n        double dif = 0;\n        double dea = 0;\n        double macd = 0;\n\n        for (int i = 0; i < quotesList.size(); i++) {\n            Quotes quotes = quotesList.get(i);\n            if (i == 0) {\n                ema12 = quotes.c;\n                ema26 = quotes.c;\n            } else {\n                ema12 = (d1 - 1) / (d1 + 1.0) * ema12 + 2.0 / (d1 + 1) * quotes.c;\n                ema26 = (d2 - 1) / (d2 + 1.0) * ema26 + 2.0 / (d2 + 1) * quotes.c;\n            }\n            //计算dif\n            dif = ema12 - ema26;\n\n            //计算dea\n            if (i == 0) {\n                dea = 0;\n            } else {\n                dea = dea * 8 / 10.0 + dif * 2 / 10.0;\n            }\n\n            //计算macd\n            macd = 2 * (dif - dea);\n\n            quotes.dif = dif;\n            quotes.dea = dea;\n            quotes.macd = macd;\n\n            //计算结束\n            //打印日志\n            //Log.e(TAG, \"calculateMACD: dif:\" + quotes.dif + \",dea:\" + quotes.dea + \",macd:\" + macd);\n        }\n\n    }\n\n    public static void calculateRSI(List<Quotes> quotesList) {\n        calculateRSI(quotesList, 6);\n        calculateRSI(quotesList, 12);\n        calculateRSI(quotesList, 24);\n    }\n\n    /**\n     * 【该算法已核实】计算RSI。RSI(x,y,z)，一般取RSI(6,12,24)。\n     * RSI(x,y,z)，x、y、z均为周期单位，计算算法一致，只是周期不同。\n     * RSIx,在周期x内，upSum=\"在周期x内的上涨总点数\"，downSum=\"在周期x内的下跌总点数\"；`RSIx=upSum/(upSum+downSum)*100`;\n     * 注意：RSIx对于最开始的x+1周期内，不存在对应RSI,在图像上表示就是不显示对应RSIx即可。\n     *\n     * @param quotes 对应的数据集合\n     * @param period 周期\n     */\n    public static void calculateRSI(List<Quotes> quotes, int period) {\n        //容错\n        if (quotes == null || quotes.isEmpty()) return;\n        if (period <= 0) period = 6;\n        //period单位的上涨点数\n        double upSum = 0f;\n        //period单位的下跌点数\n        double downSum = 0f;\n        //差值\n        double dis;\n        //最后计算的值\n        double rsi;\n        for (int i = 0; i < quotes.size(); i++) {\n            Quotes q = quotes.get(i);\n            if (i > 0) {\n                dis = q.c - quotes.get(i - 1).c;\n                if (dis >= 0) {\n                    upSum += dis;\n                } else {\n                    downSum -= dis;\n                }\n\n                //上面加，这里减。要保证累计的和周期为：period\n                if (i + 1 > period) {\n                    dis = quotes.get(i - period + 1).c - quotes.get(i - period).c;\n                    if (dis >= 0) {\n                        upSum -= dis;\n                    } else {\n                        downSum += dis;\n                    }\n                    rsi = upSum / (upSum + downSum) * 100;\n                    if (period == 6) q.rsi6 = rsi;\n                    else if (period == 12) q.rsi12 = rsi;\n                    else if (period == 24) q.rsi24 = rsi;\n                    else Log.e(TAG, \"calculateRSI: 不存在该周期：\" + period);\n                }\n            }\n        }\n\n    }\n\n\n    /**\n     * 【该算法已核实】计算公式：MA =(C1+C2+C3+C4+C5+...+Cn)/n,其中C为收盘价n为移动平均周期数。\n     * 例如现货黄金的5日移动平均价格计算方法为：MA5=(前四天收盘价+前三天收盘价+前天收盘价+昨天收盘价+今天收盘价)/5。\n     * 特殊的，假如数据集合中最开始的n个数据，是没法计算MAn的。这里的处理方式是不计算，绘制时直接不绘制对应MA即可。\n     *\n     * @param quotesList 数据集合\n     * @param period     MAn中的n,周期，一般是：5、10、20、30、60。\n     */\n    public static void calculateMA(List<Quotes> quotesList, int period, KViewType.MaType maType) {\n        boolean isMaster = true;\n        if (maType == KViewType.MaType.volMa5 || maType == KViewType.MaType.volMa10)\n            isMaster = false;\n\n        if (quotesList == null || quotesList.isEmpty()) return;\n\n        if (!isMaster && quotesList.get(0).vol <= 0)\n            throw new IllegalArgumentException(\"请确保设置vol参数\");\n\n        if (period < 0 || period > quotesList.size() - 1) return;\n\n        //包含今日的n日和\n        double sum = 0;\n        for (int i = 0; i < quotesList.size(); i++) {\n            //计算和\n            Quotes quotes = quotesList.get(i);\n            sum += isMaster ? quotes.c : quotes.vol;\n            if (i > period - 1) {\n                Quotes q = quotesList.get(i - period);\n                sum -= isMaster ? q.c : q.vol;\n            }\n            //边界\n            if (i < period - 1) {\n                continue;\n            }\n            double result = sum / period;\n            if (period == 5) {\n                if (isMaster) quotes.ma5 = result;\n                else quotes.volMa5 = result;\n            } else if (period == 10) {\n                if (isMaster) quotes.ma10 = result;\n                else quotes.volMa10 = result;\n            } else if (period == 20) {\n                if (isMaster) quotes.ma20 = result;\n                else {\n                    Log.e(TAG, \"calculateMA: 没有该种period：\" + period + \",\" + maType);\n                }\n            } else {\n                Log.e(TAG, \"calculateMA: 没有该种period：\" + period + \",\" + maType);\n                return;\n            }\n\n        }\n    }\n\n\n    /**\n     * 【该算法已核实】BOLL(n)计算公式：\n     * MA=n日内的收盘价之和÷n。\n     * MD=n日的平方根（C－MA）的两次方之和除以n\n     * MB=（n－1）日的MA\n     * UP=MB+k×MD\n     * DN=MB－k×MD\n     * K为参数，可根据股票的特性来做相应的调整，一般默认为2\n     *\n     * @param quotesList 数据集合\n     * @param period     周期，一般为26\n     * @param k          参数，可根据股票的特性来做相应的调整，一般默认为2\n     */\n    public static void calculateBOLL(List<Quotes> quotesList, int period, int k) {\n        if (quotesList == null || quotesList.isEmpty()) return;\n        if (period < 0 || period > quotesList.size() - 1) return;\n\n        double up;//上轨线\n        double mb;//中轨线\n        double dn;//下轨线\n\n        //n日\n        double sum = 0;\n        //n-1日\n        double sum2 = 0;\n        for (int i = 0; i < quotesList.size(); i++) {\n            Quotes quotes = quotesList.get(i);\n            sum += quotes.c;\n            sum2 += quotes.c;\n            if (i > period - 1)\n                sum -= quotesList.get(i - period).c;\n            if (i > period - 2)\n                sum2 -= quotesList.get(i - period + 1).c;\n\n            //这个范围不计算，在View上的反应就是不显示这个范围的boll线\n            if (i < period - 1)\n                continue;\n\n            //n日MA\n            double ma = sum / period;\n            //n-1日MA\n            double ma2 = sum2 / (period - 1);\n            double md = 0;\n            for (int j = i + 1 - period; j <= i; j++) {\n                //n日\n                md += Math.pow(quotesList.get(j).c - ma, 2);\n            }\n            md = Math.sqrt(md / period);\n            //(n－1）日的MA\n            mb = ma2;\n            up = mb + k * md;\n            dn = mb - k * md;\n\n            quotes.up = up;\n            quotes.mb = mb;\n            quotes.dn = dn;\n        }\n    }\n\n    public static void calculateBOLL(List<Quotes> quotesList) {\n        calculateBOLL(quotesList, 26, 2);\n    }\n\n    /**\n     * 找到单个报价中的最小值\n     *\n     * @param quotes\n     * @param masterType\n     * @return\n     */\n    public static double getMasterMinY(Quotes quotes, KViewType.MasterIndicatrixType masterType) {\n        double min = Integer.MAX_VALUE;\n        //ma\n        if (masterType == KViewType.MasterIndicatrixType.MA || masterType == KViewType.MasterIndicatrixType.MA_BOLL) {\n            if (quotes.ma5 != 0 && quotes.ma5 < min) {\n                min = quotes.ma5;\n            }\n            if (quotes.ma10 != 0 && quotes.ma10 < min) {\n                min = quotes.ma10;\n            }\n            if (quotes.ma20 != 0 && quotes.ma20 < min) {\n                min = quotes.ma20;\n            }\n        }\n        //boll\n        if (masterType == KViewType.MasterIndicatrixType.BOLL || masterType == KViewType.MasterIndicatrixType.MA_BOLL) {\n            //boll\n            if (quotes.mb != 0 && quotes.mb < min) {\n                min = quotes.mb;\n            }\n            if (quotes.up != 0 && quotes.up < min) {\n                min = quotes.up;\n            }\n            if (quotes.dn != 0 && quotes.dn < min) {\n                min = quotes.dn;\n            }\n        }\n        //quotes\n        if (quotes.l != 0 && quotes.l < min) {\n            min = quotes.l;\n        }\n        //没有找到\n        if (min == Integer.MAX_VALUE) {\n            min = 0;\n        }\n        return min;\n\n    }\n\n    /**\n     * 找到单个报价中的最大值\n     *\n     * @param quotes\n     * @param masterType\n     * @return\n     */\n    public static double getMasterMaxY(Quotes quotes, KViewType.MasterIndicatrixType masterType) {\n        double max = Integer.MIN_VALUE;\n        //ma\n        //只有在存在ma的情况下才计算\n        if (masterType == KViewType.MasterIndicatrixType.MA || masterType == KViewType.MasterIndicatrixType.MA_BOLL) {\n            if (quotes.ma5 != 0 && quotes.ma5 > max) {\n                max = quotes.ma5;\n            }\n            if (quotes.ma10 != 0 && quotes.ma10 > max) {\n                max = quotes.ma10;\n            }\n            if (quotes.ma20 != 0 && quotes.ma20 > max) {\n                max = quotes.ma20;\n            }\n        }\n\n        //boll\n        if (masterType == KViewType.MasterIndicatrixType.BOLL || masterType == KViewType.MasterIndicatrixType.MA_BOLL) {\n            if (quotes.mb != 0 && quotes.mb > max) {\n                max = quotes.mb;\n            }\n            if (quotes.up != 0 && quotes.up > max) {\n                max = quotes.up;\n            }\n            if (quotes.dn != 0 && quotes.dn > max) {\n                max = quotes.dn;\n            }\n        }\n        //quotes\n        if (quotes.h != 0 && quotes.h > max) {\n            max = quotes.h;\n        }\n        //没有找到\n        if (max == Integer.MIN_VALUE) {\n            max = 0;\n        }\n        return max;\n\n    }\n\n    /**\n     * 副图：找到单个报价中的最小值\n     *\n     * @param quotes\n     * @param minorType\n     * @return\n     */\n    public static double getMinorMinY(Quotes quotes, KViewType.MinorIndicatrixType minorType) {\n        double min = Integer.MAX_VALUE;\n        //macd\n        if (minorType == KViewType.MinorIndicatrixType.MACD) {\n            if (quotes.dif != 0 && quotes.dif < min) {\n                min = quotes.dif;\n            }\n            if (quotes.dea != 0 && quotes.dea < min) {\n                min = quotes.dea;\n            }\n            if (quotes.macd != 0 && quotes.macd < min) {\n                min = quotes.macd;\n            }\n        }\n        //RSI\n        if (minorType == KViewType.MinorIndicatrixType.RSI) {\n            if (quotes.rsi6 != 0 && quotes.rsi6 < min) {\n                min = quotes.rsi6;\n            }\n            if (quotes.rsi12 != 0 && quotes.rsi12 < min) {\n                min = quotes.rsi12;\n            }\n            if (quotes.rsi24 != 0 && quotes.rsi24 < min) {\n                min = quotes.rsi24;\n            }\n        }\n        //KDJ\n        if (minorType == KViewType.MinorIndicatrixType.KDJ) {\n            if (quotes.k != 0 && quotes.k < min) {\n                min = quotes.k;\n            }\n            if (quotes.d != 0 && quotes.d < min) {\n                min = quotes.d;\n            }\n            if (quotes.j != 0 && quotes.j < min) {\n                min = quotes.j;\n            }\n        }\n        //没有找到\n        if (min == Integer.MAX_VALUE) {\n            min = 0;\n        }\n        return min;\n\n    }\n\n    /**\n     * 副图：找到单个报价中的最大值\n     *\n     * @param quotes\n     * @param minorType\n     * @return\n     */\n    public static double getMinorMaxY(Quotes quotes, KViewType.MinorIndicatrixType minorType) {\n        double max = Integer.MIN_VALUE;\n        //macd\n        if (minorType == KViewType.MinorIndicatrixType.MACD) {\n            if (quotes.dif != 0 && quotes.dif > max) {\n                max = quotes.dif;\n            }\n            if (quotes.dea != 0 && quotes.dea > max) {\n                max = quotes.dea;\n            }\n            if (quotes.macd != 0 && quotes.macd > max) {\n                max = quotes.macd;\n            }\n        }\n        //RSI\n        if (minorType == KViewType.MinorIndicatrixType.RSI) {\n            if (quotes.rsi6 != 0 && quotes.rsi6 > max) {\n                max = quotes.rsi6;\n            }\n            if (quotes.rsi12 != 0 && quotes.rsi12 > max) {\n                max = quotes.rsi12;\n            }\n            if (quotes.rsi24 != 0 && quotes.rsi24 > max) {\n                max = quotes.rsi24;\n            }\n        }\n        //KDJ\n        if (minorType == KViewType.MinorIndicatrixType.KDJ) {\n            if (quotes.k != 0 && quotes.k > max) {\n                max = quotes.k;\n            }\n            if (quotes.d != 0 && quotes.d > max) {\n                max = quotes.d;\n            }\n            if (quotes.j != 0 && quotes.j > max) {\n                max = quotes.j;\n            }\n        }\n        //没有找到\n        if (max == Integer.MIN_VALUE) {\n            max = 0;\n        }\n        return max;\n\n    }\n\n    /**\n     * 量图：找到最大值\n     *\n     * @param quotes\n     * @return\n     */\n    public static double getVolMaxY(Quotes quotes) {\n        double max = Integer.MIN_VALUE;\n        //vol、volma5,volma10\n        if (quotes.vol != 0 && quotes.vol > max) {\n            max = quotes.vol;\n        }\n        if (quotes.volMa5 != 0 && quotes.volMa5 > max) {\n            max = quotes.volMa5;\n        }\n        if (quotes.volMa10 != 0 && quotes.volMa10 > max) {\n            max = quotes.volMa10;\n        }\n        return max;\n    }\n\n    /**\n     * 量图：找到最小值\n     *\n     * @param quotes\n     * @return\n     */\n    public static double getVolMinY(Quotes quotes) {\n        double min = Integer.MAX_VALUE;\n        //vol、volma5,volma10\n        if (quotes.vol != 0 && quotes.vol < min) {\n            min = quotes.vol;\n        }\n        if (quotes.volMa5 != 0 && quotes.volMa5 < min) {\n            min = quotes.volMa5;\n        }\n        if (quotes.volMa10 != 0 && quotes.volMa10 < min) {\n            min = quotes.volMa10;\n        }\n        return min;\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/KBaseView.java",
    "content": "package com.tophold.trade.view.kview;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.DashPathEffect;\nimport android.graphics.Paint;\nimport android.support.annotation.Nullable;\nimport android.support.v4.view.GestureDetectorCompat;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.MotionEvent;\nimport android.view.ScaleGestureDetector;\nimport android.widget.Toast;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.tophold.trade.R;\nimport com.tophold.trade.utils.StringUtils;\nimport com.tophold.trade.view.BaseView;\n\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更细日期 ：2018/01/14 12:03\n * 描 述 ：该View是KView的父类。\n * 提供各种基础能力，包括边框、边距、内虚线以及其它公共参数的初始化操作。\n * ============================================================\n **/\npublic abstract class KBaseView extends BaseView {\n\n    /**\n     * 默认参数及常量\n     */\n    //右侧内边距，默认情况下结束点距离右边边距（单位：sp）\n    protected static float DEF_INNER_RIGHT_BLANK_PADDING = 60;\n\n    //加载更多阀值。当在左侧不可见范围内还剩多少数据时开始加载更多。（单位：数据个数）\n    protected static int def_minlen_loadmore = 10;\n\n    //缩放最小值，该值理论上可以最小为3。为了美观，这个值不能太小，不然就成一条线了。不能定义为final,程序可能会对该值进行修改（容错）\n    protected static int def_scale_minnum = 10;\n    //缩放最大值，该值最大理论上可为数据集合的大小\n    protected static int def_scale_maxnum = 300;\n\n    //上下左右padding，这里不再采用系统属性padding，因为用户容易忘记设置padding,直接在这里更改即可。\n    protected float mBasePaddingTop = 20;\n    protected float mBasePaddingBottom = 10;\n    protected float mBasePaddingLeft = 8;\n    protected float mBasePaddingRight = 90;\n\n    //可见的显示的条数，屏幕上显示的并不是所有的数据，只是部分数据，这个数据就是“可见的条数”\n    protected int mShownMaxCount = 30;\n    //默认产品小数位数\n    protected int mDigits = 4;\n\n    // 注意，遵循取前不取后，因此mEndIndex这个点不应该取到,但是mBeginIndex会取到。\n    //数据开始位置，数据集合的起始位置\n    protected int mBeginIndex = 0;\n    //数据的结束位置，这里之所以定义结束位置，因为数据可能会小于mShownMaxCount。\n    protected int mEndIndex;\n    //数据集合\n    protected List<Quotes> mQuotesList;\n\n    //默认情况下结束点距离右边边距\n    protected float mInnerRightBlankPadding = DEF_INNER_RIGHT_BLANK_PADDING;\n    //为了美观，容器内（边框内部的折线图距离外边框线的上下距离）上面有一定间距，下面也有一定的间距。\n    protected float mInnerTopBlankPadding = 60;\n    protected float mInnerBottomBlankPadding = 60;\n\n\n    //事件监听回调\n    protected KViewListener.MasterTouchListener mMasterTouchListener;\n    //是否可以加载更多,出现这个属性的原因，防止多次加载更多，不可修改\n    protected boolean mCanLoadMore = true;\n\n\n    /**\n     * 绘制分时图：\n     */\n\n    //每一个x、y轴的一个单元的的宽和高\n    //根据可见数量和有效宽度计算单位x大小\n    protected float mPerX;\n    //根据最大最小close价格计算的的单位y大小。该参数已废弃，统一采用mPerY。\n    //protected float mClosePerY;\n    //该参数的具体逻辑由子类去实现\n    protected float mPerY;\n\n    //X轴:起始位置的时间和结束位置的时间\n    protected Quotes mBeginQuotes;\n    protected Quotes mEndQuotes;\n\n\n    /**\n     * 左右拖动思路：这里开始处理分时图的左右移动问题，思路：当手指移动时，会有移动距离（A），我们又有x轴的单位距离(B)，\n     * 所以可以计算出来需要移动的个数（C=A/B,注意向上取整）。\n     * 这个时候，就可以确定新的开始位置（D）和新的结束位置（E）：\n     * D=mBeginIndex±C,E=mEndIndex干C，正负号取决于移动方向。\n     */\n    //手指按下的个数\n    protected int mFingerPressedCount;\n    //是否是向右拉，不可修改\n    protected boolean mPullRight = false;\n    //按下的x、y轴坐标\n    protected float mPressedX;\n    protected float mPressedY;\n    //按下的时刻\n    protected long mPressTime;\n    //手指移动的类型，默认在最后边\n    protected KViewType.PullType mPullType = KViewType.PullType.PULL_RIGHT_STOP;\n\n\n    /**\n     * 缩放思路：所谓缩放，也是计算新的起始位置和结束位置。这里根据缩放因子detector.getScaleFactor()计算新的可见个数（x缩放因子即可）。\n     * 当放大时，可见的数据集合的个数(A)应该减少。detector.getScaleFactor()(B的范围[1,2)),\n     * 这个时候可以新的可见数据集合（C）可以考虑采用C=A-A*(B-1);当然这样计算是否准确，还需要商榷。\n     * 思路简单，但是这里细节比较多，具体可以参考代码。see:mOnScaleGestureListener->onScale\n     */\n\n    protected ScaleGestureDetector mScaleGestureDetector;\n\n    protected GestureDetectorCompat mFlingDetector;\n\n    //移动的模式：是一点一点移动还是具有onFling()效果？现在onfling效果有点问题\n    protected KViewType.MoveType mMoveType = KViewType.MoveType.STEP;\n\n\n    /**\n     * 画笔\n     */\n    //画笔:正在加载中\n    protected Paint mLoadingPaint;\n    protected float mLoadingTextSize = 20;\n    protected int mLoadingTextColor;\n    protected final String mLoadingText = \"数据加载，请稍后\";\n    //是否显示loading,在入场的时候，数据还没有加载时进行显示。逻辑判断使用，不可更改\n    protected boolean mDrawLoadingPaint = true;\n\n    //画笔:最外面的上下左右的框\n    protected Paint mOuterPaint;\n    protected float mOuterLineWidth = 1;\n    protected int mOuterLineColor;\n\n    //画笔:外围X、Y轴线文字\n    protected Paint mXYTxtPaint;\n    //x、y轴指示文字字体的大小\n    protected final float mXYTxtSize = 14;\n    protected int mXYTxtColor;\n    //右侧文字距离右边线线的距离\n    protected final float mRightTxtPadding = 4;\n    //底部文字距离底部线的距离\n    protected final float mBottomTxtPadding = 20;\n\n\n    //画笔:内部xy轴虚线\n    protected Paint mInnerXyPaint;\n    protected float mInnerXyLineWidth = 1;\n    protected int mInnerXyLineColor;\n    //是否是虚线，可更改\n    protected boolean mIsInnerXyLineDashed = true;\n    //是否显示内部x虚线\n    protected boolean mIsShowInnerX = true;\n    //是否显示内部y虚线\n    protected boolean mIsShowInnerY = true;\n\n    //画笔：非长按下主图指标图例\n    protected Paint mLegendPaint;\n    protected int mLegendColor;\n    //距离上方border的距离(单位：px)\n    protected double mLegendPaddingTop = 30;\n    //这个是文字框的结束位置距离右侧的距离\n    protected double mLegendPaddingRight = 10;\n    protected float mLegendTxtSize = 15;\n    protected int mLineWidth = 1;\n\n    //长按下主图指标图例\n    //这个是文字框的结束位置距离右侧的距离\n    protected double mLegendPaddingLeft = 10;\n    //同时显示ma和boll上下的间距\n    protected double mLegendTxtTopPadding = 0;\n\n\n    //是否绘制长按十字，逻辑判断使用，不可更改\n    protected boolean mDrawLongPress = false;\n\n    //滑动点的x轴坐标，滑动使用，记录当前滑动点的x坐标\n    protected float mMovingX;\n\n    //画笔:长按的十字线\n    protected Paint mLongPressPaint;\n    protected int mLongPressColor;\n    protected float mLongPressLineWidth = 1.5f;\n    //长按对应的对象\n    protected Quotes mCurrLongPressQuotes;\n\n\n    public KBaseView(Context context) {\n        this(context, null);\n    }\n\n    public KBaseView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public KBaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initAttrs();\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n        super.onLayout(changed, left, top, right, bottom);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        //默认加载loading界面\n//        showLoadingPaint(canvas);\n//        if (mQuotesList == null || mQuotesList.isEmpty()) {\n//            return;\n//        }\n        drawOuterLine(canvas);\n        drawInnerXy(canvas);\n    }\n\n    @Override\n    public boolean onTouchEvent(MotionEvent event) {\n        //按下的手指个数\n        mFingerPressedCount = event.getPointerCount();\n        switch (event.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                mPressedX = event.getX();\n                mPressTime = event.getDownTime();\n                break;\n            case MotionEvent.ACTION_MOVE:\n                if (event.getEventTime() - mPressTime > def_longpress_length) {\n                    innerLongClickListener(event.getX(), event.getY());\n                }\n                //判断是否是手指移动\n                float currentPressedX = event.getX();\n                float moveLen = currentPressedX - mPressedX;\n                //重置当前按下的位置\n                mPressedX = currentPressedX;\n                if (Math.abs(moveLen) > def_pull_length &&\n                        mFingerPressedCount == 1 &&\n                        !mDrawLongPress &&\n                        mMoveType == KViewType.MoveType.STEP) {\n                    //移动k线图\n                    innerMoveViewListener(moveLen);\n                }\n                break;\n            case MotionEvent.ACTION_UP:\n                //单击事件\n                if (event.getEventTime() - mPressTime < def_clickpress_length) {\n                    //单击并且是在绘制十字\n                    if (mDrawLongPress) {\n                        //取消掉长按十字\n                        innerHiddenLongClick();\n                    } else {\n                        //响应单击事件\n                        innerClickListener();//这个事件传递下去\n                    }\n                }\n                break;\n            default:\n                break;\n        }\n        return true;\n    }\n\n    private void initAttrs() {\n        initColorRes();\n        initPaintRes();\n        initData();\n    }\n\n    private void initData() {\n        mQuotesList=new ArrayList<>();\n    }\n\n    private void initColorRes() {\n        mOuterLineColor = getColor(R.color.color_kview_outerStrokeColor);\n        mLoadingTextColor = getColor(R.color.color_kview_loadingTxtColor);\n        mInnerXyLineColor = getColor(R.color.color_kview_innerXyDashColor);\n        mXYTxtColor = getColor(R.color.color_timeSharing_xYTxtColor);\n        mLegendColor = getColor(R.color.color_masterView_legendColor);\n        mLongPressColor = getColor(R.color.color_timeSharing_longPressLineColor);\n    }\n\n    private void initPaintRes() {\n        initLoadingPaint();\n        initOuterPaint();\n        initInnerXyPaint();\n        initXyTxtPaint();\n        initLegendPaint();\n        initLongPressPaint();\n    }\n\n    protected void initLoadingPaint() {\n        mLoadingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mLoadingPaint.setColor(mLoadingTextColor);\n        mLoadingPaint.setTextSize(mLoadingTextSize);\n    }\n\n\n    protected void initOuterPaint() {\n        mOuterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mOuterPaint.setColor(mOuterLineColor);\n        mOuterPaint.setStrokeWidth(mOuterLineWidth);\n    }\n\n    protected void initInnerXyPaint() {\n        mInnerXyPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mInnerXyPaint.setColor(mInnerXyLineColor);\n        mInnerXyPaint.setStrokeWidth(mInnerXyLineWidth);\n        mInnerXyPaint.setStyle(Paint.Style.STROKE);\n        if (mIsInnerXyLineDashed) {\n            setLayerType(LAYER_TYPE_SOFTWARE, null);\n            mInnerXyPaint.setPathEffect(new DashPathEffect(new float[]{5, 5}, 0));\n        }\n    }\n\n    protected void initXyTxtPaint() {\n        mXYTxtPaint = new Paint();\n        mXYTxtPaint.setColor(mXYTxtColor);\n        mXYTxtPaint.setTextSize(mXYTxtSize);\n        mXYTxtPaint.setAntiAlias(true);\n    }\n\n    private void initLegendPaint() {\n        mLegendPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mLegendPaint.setColor(mLegendColor);\n        mLegendPaint.setStrokeWidth(mLineWidth);\n        mLegendPaint.setTextSize(mLegendTxtSize);\n    }\n\n    protected void initLongPressPaint() {\n        mLongPressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mLongPressPaint.setColor(mLongPressColor);\n        mLongPressPaint.setStrokeWidth(mLongPressLineWidth);\n        mLongPressPaint.setStyle(Paint.Style.STROKE);\n    }\n\n    protected void showLoadingPaint(Canvas canvas) {\n        if (!mDrawLoadingPaint) return;\n        //这里特别注意，x轴的起始点要减去文字宽度的一半\n        canvas.drawText(mLoadingText, mBaseWidth / 2 - mLoadingPaint.measureText(mLoadingText) / 2,\n                mBaseHeight / 2, mLoadingPaint);\n    }\n\n    protected void drawOuterLine(Canvas canvas) {\n        //先绘制x轴\n        canvas.drawLine(mBasePaddingLeft, mBasePaddingTop,\n                mBaseWidth - mBasePaddingRight, mBasePaddingTop, mOuterPaint);\n        canvas.drawLine(mBasePaddingLeft, mBaseHeight - mBasePaddingBottom,\n                mBaseWidth - mBasePaddingRight, mBaseHeight - mBasePaddingBottom, mOuterPaint);\n\n        //绘制y轴\n        canvas.drawLine(mBasePaddingLeft, mBasePaddingTop,\n                mBasePaddingLeft, mBaseHeight - mBasePaddingBottom, mOuterPaint);\n        canvas.drawLine(mBaseWidth - mBasePaddingRight, mBasePaddingTop,\n                mBaseWidth - mBasePaddingRight, mBaseHeight - mBasePaddingBottom, mOuterPaint);\n    }\n\n    /**\n     * 绘制内部x/y轴虚线\n     *\n     * @param canvas\n     */\n    protected void drawInnerXy(Canvas canvas) {\n        if (isShowInnerX())\n            drawInnerX(canvas);\n        if (isShowInnerY())\n            drawInnerY(canvas);\n    }\n\n    private void drawInnerY(Canvas canvas) {\n        //绘制y轴\n        double perWidth = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight) / 4;\n        for (int i = 1; i <= 3; i++) {\n            canvas.drawLine((float) (mBasePaddingLeft + perWidth * i), mBasePaddingTop,\n                    (float) (mBasePaddingLeft + perWidth * i), mBaseHeight - mBasePaddingBottom,\n                    mInnerXyPaint);\n        }\n    }\n\n    private void drawInnerX(Canvas canvas) {\n        //先绘制x轴\n        //计算每一段x的高度\n        double perhight = (mBaseHeight - mBasePaddingTop - mBasePaddingBottom) / 4;\n        for (int i = 1; i <= 3; i++) {\n            canvas.drawLine(mBasePaddingLeft, (float) (mBasePaddingTop + perhight * i),\n                    mBaseWidth - mBasePaddingRight, (float) (mBasePaddingTop + perhight * i),\n                    mInnerXyPaint);\n        }\n    }\n\n    // 只需要把画笔颜色置为透明即可\n    protected void hiddenLoadingPaint() {\n        mLoadingPaint.setColor(0x00000000);\n        mDrawLoadingPaint = false;\n    }\n\n    /**\n     * 加载更多失败，在这里添加逻辑\n     */\n    public void loadMoreError() {\n        mCanLoadMore = true;\n        Toast.makeText(mContext, \"加载更多失败\", Toast.LENGTH_SHORT).show();\n    }\n\n    /**\n     * 加载更多成功，在这里添加逻辑\n     */\n    public void loadMoreSuccess() {\n        mCanLoadMore = true;\n        Toast.makeText(mContext, \"加载更多成功\", Toast.LENGTH_SHORT).show();\n    }\n\n    /**\n     * 正在加载更多，在这里添加逻辑\n     */\n    public void loadMoreIng() {\n        mCanLoadMore = false;\n        Toast.makeText(mContext, \"正在加载更多\", Toast.LENGTH_SHORT).show();\n    }\n\n    /**\n     * 没有更多数据，在这里添加逻辑\n     */\n    public void loadMoreNoData() {\n        mCanLoadMore = false;\n        Toast.makeText(mContext, \"加载更多，没有数据了...\", Toast.LENGTH_SHORT).show();\n    }\n\n\n    /**\n     * 数据设置入口\n     *\n     * @param quotesList\n     * @param masterTouchListener\n     */\n    public void setTimeSharingData(List<Quotes> quotesList, KViewListener.MasterTouchListener masterTouchListener) {\n        //绑定监听\n        mMasterTouchListener = masterTouchListener;\n        //添加数据\n        setTimeSharingData(quotesList);\n    }\n\n    /**\n     * 数据设置入口\n     *\n     * @param quotesList\n     */\n    public void setTimeSharingData(List<Quotes> quotesList) {\n        if (quotesList == null || quotesList.isEmpty()) {\n            Toast.makeText(mContext, \"数据异常\", Toast.LENGTH_SHORT).show();\n            Log.e(TAG, \"setKViewData: 数据异常\");\n            return;\n        }\n        mQuotesList.addAll(quotesList);\n        //数据过来，隐藏加载更多\n        hiddenLoadingPaint();\n\n        //寻找开始位置和结束位置\n        seekBeginAndEndByNewer();\n\n        //寻找边界和计算单元数据大小\n        seekAndCalculateCellData();\n    }\n\n    /**\n     * 获取最新数据时（包括第一次进来）获取可见数据的开始位置和结束位置。来最新数据或者刚加载的时候，计算开始位置和结束位置。\n     * 特别注意，最新的数据在最后面，所以数据范围应该是[(size-mShownMaxCount)~size)\n     */\n    protected void seekBeginAndEndByNewer() {\n        int size = mQuotesList.size();\n        if (size >= mShownMaxCount) {\n            mBeginIndex = size - mShownMaxCount;\n            mEndIndex = mBeginIndex + mShownMaxCount;\n        } else {\n            mBeginIndex = 0;\n            mEndIndex = mBeginIndex + mQuotesList.size();\n        }\n    }\n\n    /**\n     * 实时推送过来的数据，实时更新\n     *\n     * @param quotes\n     * @param period 对应的数据的类型 ms\n     */\n    public void pushingTimeSharingData(Quotes quotes, long period) {\n        if (quotes == null) {\n            Toast.makeText(mContext, \"数据异常\", Toast.LENGTH_SHORT).show();\n            Log.e(TAG, \"setKViewData: 数据异常\");\n            return;\n        }\n        if (StringUtils.isEmpty(mQuotesList)) return;\n\n\n        /**\n         * 对于新推送过来的数据，需要判断和列表中最新的数据的时间差进行对比。对比和View的类型有关，比如1min的\n         * 时间差是60s，如果小于60s,就更新最新一条的最大值和最小值；否则添加进去。\n         */\n        Quotes q = mQuotesList.get(mQuotesList.size() - 1);\n        if (quotes.t < q.t) return;\n        if (period != 0 && ((quotes.t - q.t) / 1000.0) <= period / 1000) {\n            //这个时候替换最后一个原有数据\n            q.c = quotes.c;//绘制分时图是根据闭市价格算的\n\n            //判断最大值和最小值，及时更新\n            if (quotes.c > q.h) q.h = quotes.c;\n            if (quotes.c < q.l) q.l = quotes.c;\n\n\n            mQuotesList.set(mQuotesList.size() - 1, q);\n        } else {\n            //new ?Add it!\n            mQuotesList.add(quotes);\n        }\n\n\n        //如果是在左右移动，则不去实时更新K线图，但是要把数据加进去\n        if (mPullType == KViewType.PullType.PULL_RIGHT_STOP) {\n            //Log.e(TAG, \"pushKViewData: 处理实时更新操作...\");\n            seekBeginAndEndByNewer();\n            seekAndCalculateCellData();\n        }\n    }\n\n    /**\n     * 加载更多数据。所谓加载更多数据，加载的是历史数据。而整个数据是从左到右依次为旧的->新的，所以新过来的数据是旧的，\n     * 要插入到最左边。而这个时候，应该要保持mBeginIndex和mEndIndx和插入之前一致（不然k线会突然闪动一下）。\n     *\n     *\n     * @param quotesList\n     */\n    public void loadMoreTimeSharingData(List<Quotes> quotesList) {\n        if (quotesList == null || quotesList.isEmpty()) {\n            Toast.makeText(mContext, \"数据异常\", Toast.LENGTH_SHORT).show();\n            Log.e(TAG, \"setKViewData: 数据异常\");\n            return;\n        }\n        mQuotesList.addAll(0, quotesList);\n\n        //到这里就可以判断，加载更对成功了\n        loadMoreSuccess();\n\n        //特别特别注意，加载更多之后，不应该更新起始位置和结束位置，\n        //因为可能在加载的过程中，原来的意图是在最左边，但是加载完毕后，又不在最左边了。\n        //因此，只要保持原来的起始位置和结束位置即可。【原来：指的是视觉上的原来】\n        int addSize = quotesList.size();\n        mBeginIndex += addSize;\n        mEndIndex += addSize;\n\n        //重新计算perx\\pery等\n        seekAndCalculateCellData();\n    }\n\n\n    /**\n     * 寻找边界和计算单元数据大小。寻找:x轴开始位置数据和结束位置的model、y轴的最大数据和最小数据对应的model；\n     * 计算x/y轴数据单元大小。这个交给子类去实现，一般情况下寻找边界需要遍历，在父类中遍历没有意义，\n     * 因为不知道子类还有什么遍历需求。因此改为抽象方法，子类实现。子类必须完成寻找边界的任务。\n     */\n    protected abstract void seekAndCalculateCellData();\n\n    public boolean isShowInnerX() {\n        return mIsShowInnerX;\n    }\n\n    public void setShowInnerX(boolean showInnerX) {\n        mIsShowInnerX = showInnerX;\n    }\n\n    public boolean isShowInnerY() {\n        return mIsShowInnerY;\n    }\n\n    public void setShowInnerY(boolean showInnerY) {\n        mIsShowInnerY = showInnerY;\n    }\n\n    protected void innerClickListener() {\n    }\n\n    protected void innerHiddenLongClick() {\n\n    }\n\n    protected void innerMoveViewListener(float moveXLen) {\n    }\n\n    protected void innerLongClickListener(float x, float y) {\n    }\n\n\n    //-----------------------对开发者暴露可以修改的参数-------\n\n\n    public static int getDef_minlen_loadmore() {\n        return def_minlen_loadmore;\n    }\n\n    public static void setDef_minlen_loadmore(int def_minlen_loadmore) {\n        KBaseView.def_minlen_loadmore = def_minlen_loadmore;\n    }\n\n    public static int getDef_scale_minnum() {\n        return def_scale_minnum;\n    }\n\n    public static void setDef_scale_minnum(int def_scale_minnum) {\n        KBaseView.def_scale_minnum = def_scale_minnum;\n    }\n\n    public static int getDef_scale_maxnum() {\n        return def_scale_maxnum;\n    }\n\n    public static void setDef_scale_maxnum(int def_scale_maxnum) {\n        KBaseView.def_scale_maxnum = def_scale_maxnum;\n    }\n\n    public float getBasePaddingTop() {\n        return mBasePaddingTop;\n    }\n\n    public KBaseView setBasePaddingTop(float basePaddingTop) {\n        mBasePaddingTop = basePaddingTop;\n        return this;\n    }\n\n    public float getBasePaddingBottom() {\n        return mBasePaddingBottom;\n    }\n\n    public KBaseView setBasePaddingBottom(float basePaddingBottom) {\n        mBasePaddingBottom = basePaddingBottom;\n        return this;\n    }\n\n    public float getBasePaddingLeft() {\n        return mBasePaddingLeft;\n    }\n\n    public KBaseView setBasePaddingLeft(float basePaddingLeft) {\n        mBasePaddingLeft = basePaddingLeft;\n        return this;\n    }\n\n    public float getBasePaddingRight() {\n        return mBasePaddingRight;\n    }\n\n    public KBaseView setBasePaddingRight(float basePaddingRight) {\n        mBasePaddingRight = basePaddingRight;\n        return this;\n    }\n\n    public int getShownMaxCount() {\n        return mShownMaxCount;\n    }\n\n    public KBaseView setShownMaxCount(int shownMaxCount) {\n        mShownMaxCount = shownMaxCount;\n        return this;\n    }\n\n    public int getDigits() {\n        return mDigits;\n    }\n\n    public KBaseView setDigits(int digits) {\n        mDigits = digits;\n        return this;\n    }\n\n    public int getBeginIndex() {\n        return mBeginIndex;\n    }\n\n    public KBaseView setBeginIndex(int beginIndex) {\n        mBeginIndex = beginIndex;\n        return this;\n    }\n\n    public int getEndIndex() {\n        return mEndIndex;\n    }\n\n    public KBaseView setEndIndex(int endIndex) {\n        mEndIndex = endIndex;\n        return this;\n    }\n\n    public List<Quotes> getQuotesList() {\n        return mQuotesList;\n    }\n\n    public KBaseView setQuotesList(List<Quotes> quotesList) {\n        mQuotesList = quotesList;\n        return this;\n    }\n\n    public float getInnerRightBlankPadding() {\n        return mInnerRightBlankPadding;\n    }\n\n    public KBaseView setInnerRightBlankPadding(float innerRightBlankPadding) {\n        mInnerRightBlankPadding = innerRightBlankPadding;\n        return this;\n    }\n\n    public float getInnerTopBlankPadding() {\n        return mInnerTopBlankPadding;\n    }\n\n    public KBaseView setInnerTopBlankPadding(float innerTopBlankPadding) {\n        mInnerTopBlankPadding = innerTopBlankPadding;\n        return this;\n    }\n\n    public float getInnerBottomBlankPadding() {\n        return mInnerBottomBlankPadding;\n    }\n\n    public KBaseView setInnerBottomBlankPadding(float innerBottomBlankPadding) {\n        mInnerBottomBlankPadding = innerBottomBlankPadding;\n        return this;\n    }\n\n    public KViewListener.MasterTouchListener getMasterTouchListener() {\n        return mMasterTouchListener;\n    }\n\n    public KBaseView setMasterTouchListener(KViewListener.MasterTouchListener masterTouchListener) {\n        mMasterTouchListener = masterTouchListener;\n        return this;\n    }\n\n    public boolean isCanLoadMore() {\n        return mCanLoadMore;\n    }\n\n    public KBaseView setCanLoadMore(boolean canLoadMore) {\n        mCanLoadMore = canLoadMore;\n        return this;\n    }\n\n    public float getPerX() {\n        return mPerX;\n    }\n\n    public KBaseView setPerX(float perX) {\n        mPerX = perX;\n        return this;\n    }\n\n    public float getPerY() {\n        return mPerY;\n    }\n\n    public KBaseView setPerY(float perY) {\n        mPerY = perY;\n        return this;\n    }\n\n    public Quotes getBeginQuotes() {\n        return mBeginQuotes;\n    }\n\n    public KBaseView setBeginQuotes(Quotes beginQuotes) {\n        mBeginQuotes = beginQuotes;\n        return this;\n    }\n\n    public Quotes getEndQuotes() {\n        return mEndQuotes;\n    }\n\n    public KBaseView setEndQuotes(Quotes endQuotes) {\n        mEndQuotes = endQuotes;\n        return this;\n    }\n\n    public int getFingerPressedCount() {\n        return mFingerPressedCount;\n    }\n\n    public KBaseView setFingerPressedCount(int fingerPressedCount) {\n        mFingerPressedCount = fingerPressedCount;\n        return this;\n    }\n\n    public boolean isPullRight() {\n        return mPullRight;\n    }\n\n    public KBaseView setPullRight(boolean pullRight) {\n        mPullRight = pullRight;\n        return this;\n    }\n\n    public float getPressedX() {\n        return mPressedX;\n    }\n\n    public KBaseView setPressedX(float pressedX) {\n        mPressedX = pressedX;\n        return this;\n    }\n\n    public float getPressedY() {\n        return mPressedY;\n    }\n\n    public KBaseView setPressedY(float pressedY) {\n        mPressedY = pressedY;\n        return this;\n    }\n\n    public long getPressTime() {\n        return mPressTime;\n    }\n\n    public KBaseView setPressTime(long pressTime) {\n        mPressTime = pressTime;\n        return this;\n    }\n\n    public KViewType.PullType getPullType() {\n        return mPullType;\n    }\n\n    public KBaseView setPullType(KViewType.PullType pullType) {\n        mPullType = pullType;\n        return this;\n    }\n\n    public ScaleGestureDetector getScaleGestureDetector() {\n        return mScaleGestureDetector;\n    }\n\n    public KBaseView setScaleGestureDetector(ScaleGestureDetector scaleGestureDetector) {\n        mScaleGestureDetector = scaleGestureDetector;\n        return this;\n    }\n\n    public Paint getLoadingPaint() {\n        return mLoadingPaint;\n    }\n\n    public KBaseView setLoadingPaint(Paint loadingPaint) {\n        mLoadingPaint = loadingPaint;\n        return this;\n    }\n\n    public float getLoadingTextSize() {\n        return mLoadingTextSize;\n    }\n\n    public KBaseView setLoadingTextSize(float loadingTextSize) {\n        mLoadingTextSize = loadingTextSize;\n        return this;\n    }\n\n    public int getLoadingTextColor() {\n        return mLoadingTextColor;\n    }\n\n    public KBaseView setLoadingTextColor(int loadingTextColor) {\n        mLoadingTextColor = loadingTextColor;\n        return this;\n    }\n\n    public String getLoadingText() {\n        return mLoadingText;\n    }\n\n    public boolean isDrawLoadingPaint() {\n        return mDrawLoadingPaint;\n    }\n\n    public KBaseView setDrawLoadingPaint(boolean drawLoadingPaint) {\n        mDrawLoadingPaint = drawLoadingPaint;\n        return this;\n    }\n\n    public Paint getOuterPaint() {\n        return mOuterPaint;\n    }\n\n    public KBaseView setOuterPaint(Paint outerPaint) {\n        mOuterPaint = outerPaint;\n        return this;\n    }\n\n    public float getOuterLineWidth() {\n        return mOuterLineWidth;\n    }\n\n    public KBaseView setOuterLineWidth(float outerLineWidth) {\n        mOuterLineWidth = outerLineWidth;\n        return this;\n    }\n\n    public int getOuterLineColor() {\n        return mOuterLineColor;\n    }\n\n    public KBaseView setOuterLineColor(int outerLineColor) {\n        mOuterLineColor = outerLineColor;\n        return this;\n    }\n\n    public Paint getXYTxtPaint() {\n        return mXYTxtPaint;\n    }\n\n    public KBaseView setXYTxtPaint(Paint XYTxtPaint) {\n        mXYTxtPaint = XYTxtPaint;\n        return this;\n    }\n\n    public float getXYTxtSize() {\n        return mXYTxtSize;\n    }\n\n    public int getXYTxtColor() {\n        return mXYTxtColor;\n    }\n\n    public KBaseView setXYTxtColor(int XYTxtColor) {\n        mXYTxtColor = XYTxtColor;\n        return this;\n    }\n\n    public float getRightTxtPadding() {\n        return mRightTxtPadding;\n    }\n\n    public float getBottomTxtPadding() {\n        return mBottomTxtPadding;\n    }\n\n    public Paint getInnerXyPaint() {\n        return mInnerXyPaint;\n    }\n\n    public KBaseView setInnerXyPaint(Paint innerXyPaint) {\n        mInnerXyPaint = innerXyPaint;\n        return this;\n    }\n\n    public float getInnerXyLineWidth() {\n        return mInnerXyLineWidth;\n    }\n\n    public KBaseView setInnerXyLineWidth(float innerXyLineWidth) {\n        mInnerXyLineWidth = innerXyLineWidth;\n        return this;\n    }\n\n    public int getInnerXyLineColor() {\n        return mInnerXyLineColor;\n    }\n\n    public KBaseView setInnerXyLineColor(int innerXyLineColor) {\n        mInnerXyLineColor = innerXyLineColor;\n        return this;\n    }\n\n    public boolean isInnerXyLineDashed() {\n        return mIsInnerXyLineDashed;\n    }\n\n    public KBaseView setInnerXyLineDashed(boolean innerXyLineDashed) {\n        mIsInnerXyLineDashed = innerXyLineDashed;\n        return this;\n    }\n\n    public Paint getLegendPaint() {\n        return mLegendPaint;\n    }\n\n    public KBaseView setLegendPaint(Paint legendPaint) {\n        mLegendPaint = legendPaint;\n        return this;\n    }\n\n    public int getLegendColor() {\n        return mLegendColor;\n    }\n\n    public KBaseView setLegendColor(int legendColor) {\n        mLegendColor = legendColor;\n        return this;\n    }\n\n    public double getLegendPaddingTop() {\n        return mLegendPaddingTop;\n    }\n\n    public KBaseView setLegendPaddingTop(double legendPaddingTop) {\n        mLegendPaddingTop = legendPaddingTop;\n        return this;\n    }\n\n    public double getLegendPaddingRight() {\n        return mLegendPaddingRight;\n    }\n\n    public KBaseView setLegendPaddingRight(double legendPaddingRight) {\n        mLegendPaddingRight = legendPaddingRight;\n        return this;\n    }\n\n    public float getLegendTxtSize() {\n        return mLegendTxtSize;\n    }\n\n    public KBaseView setLegendTxtSize(float legendTxtSize) {\n        mLegendTxtSize = legendTxtSize;\n        return this;\n    }\n\n    public int getLineWidth() {\n        return mLineWidth;\n    }\n\n    public KBaseView setLineWidth(int lineWidth) {\n        mLineWidth = lineWidth;\n        return this;\n    }\n\n    public double getLegendPaddingLeft() {\n        return mLegendPaddingLeft;\n    }\n\n    public KBaseView setLegendPaddingLeft(double legendPaddingLeft) {\n        mLegendPaddingLeft = legendPaddingLeft;\n        return this;\n    }\n\n    public double getLegendTxtTopPadding() {\n        return mLegendTxtTopPadding;\n    }\n\n    public KBaseView setLegendTxtTopPadding(double legendTxtTopPadding) {\n        mLegendTxtTopPadding = legendTxtTopPadding;\n        return this;\n    }\n\n    public boolean isDrawLongPress() {\n        return mDrawLongPress;\n    }\n\n    public KBaseView setDrawLongPress(boolean drawLongPress) {\n        mDrawLongPress = drawLongPress;\n        return this;\n    }\n\n    public float getMovingX() {\n        return mMovingX;\n    }\n\n    public KBaseView setMovingX(float movingX) {\n        mMovingX = movingX;\n        return this;\n    }\n\n    public Paint getLongPressPaint() {\n        return mLongPressPaint;\n    }\n\n    public KBaseView setLongPressPaint(Paint longPressPaint) {\n        mLongPressPaint = longPressPaint;\n        return this;\n    }\n\n    public int getLongPressColor() {\n        return mLongPressColor;\n    }\n\n    public KBaseView setLongPressColor(int longPressColor) {\n        mLongPressColor = longPressColor;\n        return this;\n    }\n\n    public float getLongPressLineWidth() {\n        return mLongPressLineWidth;\n    }\n\n    public KBaseView setLongPressLineWidth(float longPressLineWidth) {\n        mLongPressLineWidth = longPressLineWidth;\n        return this;\n    }\n\n    public Quotes getCurrLongPressQuotes() {\n        return mCurrLongPressQuotes;\n    }\n\n    public KBaseView setCurrLongPressQuotes(Quotes currLongPressQuotes) {\n        mCurrLongPressQuotes = currLongPressQuotes;\n        return this;\n    }\n\n    public KViewType.MoveType getMoveType() {\n        return mMoveType;\n    }\n\n    public KBaseView setMoveType(KViewType.MoveType moveType) {\n        mMoveType = moveType;\n        return this;\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/KLayoutView.java",
    "content": "package com.tophold.trade.view.kview;\n\nimport android.content.Context;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.widget.LinearLayout;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/03 15:38\n * 描 述 ：KView,包含主图和副图，包括手势、加载数据等\n * ============================================================\n **/\npublic class KLayoutView extends LinearLayout {\n    public static String TAG;\n    public static final float DEF_MINORHRATIO = 0.25f;\n    public static final float DEF_VOLHRATIO = 0.25f;\n    protected MasterView mMasterView;\n    protected MinorView mMinorView;\n    protected VolView mVolView;\n    //副图高度占全部高度比\n    protected float mMinorHRatio = DEF_MINORHRATIO;\n    //量图高度占全部高度比\n    protected float mVolHRatio = DEF_VOLHRATIO;\n    //是否展示副图\n    protected boolean isShowMinor = true;\n    //是否展示量图\n    protected boolean isShowVol = false;\n\n    public KLayoutView(Context context) {\n        this(context, null);\n    }\n\n    public KLayoutView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public KLayoutView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        TAG = this.getClass().getSimpleName();\n        layoutViews();\n        initDefAttrs();\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int l, int t, int r, int b) {\n        super.onLayout(changed, l, t, r, b);\n\n    }\n\n\n    private void initDefAttrs() {\n        setShowMinor(true);\n        setShowVol(false);\n    }\n\n    private void layoutViews() {\n        setOrientation(VERTICAL);\n\n        mMasterView = new MasterView(getContext());\n        // mMasterView.setBackgroundColor(getResources().getColor(R.color.color_fundView_brokenLineColor));\n        mMinorView = new MinorView(getContext());\n        // mMinorView.setBackgroundColor(getResources().getColor(R.color.color_fundView_xLineColor));\n\n        mVolView = new VolView(getContext());\n\n        //测量高度\n        measureHeight();\n\n        addView(mMasterView);\n        addView(mMinorView);\n        addView(mVolView);\n\n        mMasterView.setMinorListener(mMinorView.getMinorListener());\n        mMasterView.setVolListener(mVolView.getVolListener());\n    }\n\n    private void measureHeight() {\n        LayoutParams params = new LayoutParams(\n                LayoutParams.MATCH_PARENT, 0);\n        params.weight = 1 - mMinorHRatio - mVolHRatio;\n        mMasterView.setLayoutParams(params);\n\n\n        LayoutParams params2 = new LayoutParams(\n                LayoutParams.MATCH_PARENT, 0);\n        params2.weight = mMinorHRatio;\n        mMinorView.setLayoutParams(params2);\n\n        LayoutParams params3 = new LayoutParams(\n                LayoutParams.MATCH_PARENT, 0);\n        params3.weight = mVolHRatio;\n        mVolView.setLayoutParams(params3);\n    }\n\n\n    //-----------------------对开发者暴露可以修改的参数-------\n    public MasterView getMasterView() {\n        return mMasterView;\n    }\n\n    public KLayoutView setMasterView(MasterView masterView) {\n        mMasterView = masterView;\n        return this;\n    }\n\n    public MinorView getMinorView() {\n        return mMinorView;\n    }\n\n    public KLayoutView setMinorView(MinorView minorView) {\n        mMinorView = minorView;\n        return this;\n    }\n\n    public float getMinorHRatio() {\n        return mMinorHRatio;\n    }\n\n    public void setMinorHRatio(float minorHRatio) {\n        mMinorHRatio = minorHRatio;\n    }\n\n\n    public boolean isShowMinor() {\n        return isShowMinor;\n    }\n\n    public VolView getVolView() {\n        return mVolView;\n    }\n\n    public KLayoutView setVolView(VolView volView) {\n        mVolView = volView;\n        return this;\n    }\n\n    public float getVolHRatio() {\n        return mVolHRatio;\n    }\n\n    public KLayoutView setVolHRatio(float volHRatio) {\n        mVolHRatio = volHRatio;\n        return this;\n    }\n\n    public boolean isShowVol() {\n        return isShowVol;\n    }\n\n    @NonNull\n    private KLayoutView reloadHeight() {\n        //为什么要这样刷新？先重新测量主图和副图的高度，然后再去测量各自的seekAndCalculateCellData\n        measureHeight();\n\n        postDelayed(() -> {\n            mMasterView.seekAndCalculateCellData();\n            mMinorView.seekAndCalculateCellData();\n            mVolView.seekAndCalculateCellData();\n        }, 300);\n        return this;\n    }\n\n    /**\n     * 这个问题比较奇葩。主要原因是：整个View重新布局了大小，等于重新走了生命周期，导致各种问题。\n     * 之前一般都是只是走onDraw()方法，所以基本不会有什么问题。\n     * 现在是高度变了，因此必须重新测量。\n     * 现在下面这种实现方式仍然会有视觉上的延迟，体验不太好，暂时没有好评的解决方案。\n     * 另外：平时基本不会这样直接的主图副图显示不显示来回切换。如果在初始化的时候就设置好，不会有任何问题。\n     *\n     * @param showMinor\n     */\n    public KLayoutView setShowMinor(boolean showMinor) {\n        isShowMinor = showMinor;\n        if (!isShowMinor) {\n            mMinorHRatio = 0;\n        } else {\n            mMinorHRatio = DEF_MINORHRATIO;\n        }\n        return reloadHeight();\n    }\n\n    public KLayoutView setShowVol(boolean showVol) {\n        isShowVol = showVol;\n        if (!isShowVol) {\n            mVolHRatio = 0;\n        } else {\n            mVolHRatio = DEF_VOLHRATIO;\n        }\n        Log.d(TAG, \"setShowVol: \" + isShowVol);\n        mVolView.setShowVol(isShowVol);\n        return reloadHeight();\n\n\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/KView.java",
    "content": "package com.tophold.trade.view.kview;\n\nimport android.content.Context;\nimport android.support.annotation.Nullable;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.tophold.trade.R;\n\nimport java.util.List;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2018/03/04 11:06\n * 描 述 ：KView入口\n * ============================================================\n **/\npublic final class KView extends KLayoutView {\n\n    //主图展示的是蜡烛图还是分时图\n    protected boolean isShowTimSharing = true;\n    //设置数据精度\n    protected int mDigit = 4;\n\n    public KView(Context context) {\n        this(context, null);\n    }\n\n    public KView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public KView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initListener();\n    }\n\n\n    private void initListener() {\n        mMasterView.setMaxPostionListener((quotes, x, y) -> {\n            Log.d(TAG, \"initListener1: \" + x + \",\" + y);\n        });\n        mMasterView.setMinPostionListener((quotes, x, y) -> {\n            Log.d(TAG, \"initListener2: \" + x + \",\" + y);\n\n        });\n        mMasterView.setLastPostionListener((quotes, x, y) -> {\n            Log.d(TAG, \"initListener3: \" + x + \",\" + y);\n        });\n    }\n\n    /**\n     * 数据设置入口\n     *\n     * @param quotesList\n     */\n    public void setKViewData(List<Quotes> quotesList, KViewListener.MasterTouchListener masterTouchListener) {\n        if (quotesList == null || quotesList.isEmpty()) {\n            Toast.makeText(getContext(), \"数据异常1111\", Toast.LENGTH_SHORT).show();\n            Log.e(TAG, \"setKViewData: 数据异常111\");\n            return;\n        }\n        mMasterView.setTimeSharingData(quotesList, masterTouchListener);\n        mMinorView.setTimeSharingData(quotesList, masterTouchListener);\n        mVolView.setTimeSharingData(quotesList, masterTouchListener);\n    }\n\n    /**\n     * 实时推送过来的数据，实时更新。\n     * 这个地方可以优化：因为用户不知道什么时候可以Push过来数据，如果不处理。可能存在一种情况：数据还没加载完毕，push就过来了就会出现异常。\n     *\n     * @param quotes\n     */\n    public void pushKViewData(Quotes quotes, long period) {\n        if (quotes == null) {\n            //Toast.makeText(getContext(), \"数据异常\", Toast.LENGTH_SHORT).show();\n            //Log.e(TAG, \"setKViewData: 数据异常\");\n            return;\n        }\n        mMasterView.pushingTimeSharingData(quotes, period);\n        mMinorView.pushingTimeSharingData(quotes, period);\n        mVolView.pushingTimeSharingData(quotes, period);\n    }\n\n    /**\n     * 加载更多数据\n     *\n     * @param quotesList\n     */\n    public void loadKViewData(List<Quotes> quotesList) {\n        if (quotesList == null || quotesList.isEmpty()) {\n            Toast.makeText(getContext(), \"数据异常\", Toast.LENGTH_SHORT).show();\n            Log.e(TAG, \"setKViewData: 数据异常\");\n            return;\n        }\n        mMasterView.loadMoreTimeSharingData(quotesList);\n        mMinorView.loadMoreTimeSharingData(quotesList);\n        mVolView.loadMoreTimeSharingData(quotesList);\n    }\n\n    /**\n     * 加载更多失败，在这里添加逻辑\n     */\n    public void loadMoreError() {\n        mMasterView.loadMoreError();\n    }\n\n    /**\n     * 加载更多成功，在这里添加逻辑\n     */\n    public void loadMoreSuccess() {\n        mMasterView.loadMoreSuccess();\n    }\n\n    /**\n     * 正在加载更多，在这里添加逻辑\n     */\n    public void loadMoreIng() {\n        mMasterView.loadMoreIng();\n    }\n\n    /**\n     * 没有更多数据，在这里添加逻辑\n     */\n    public void loadMoreNoData() {\n        mMasterView.loadMoreNoData();\n    }\n\n\n    //-----------------------对开发者暴露可以修改的参数-------\n\n    public boolean isShowTimSharing() {\n        return isShowTimSharing;\n    }\n\n    public void setShowTimSharing(boolean showTimSharing) {\n        isShowTimSharing = showTimSharing;\n        mMasterView.setViewType(showTimSharing ? KViewType.MasterViewType.TIMESHARING : KViewType.MasterViewType.CANDLE);\n    }\n\n    public int getDigit() {\n        return mDigit;\n    }\n\n    public void setDigit(int digit) {\n        mDigit = digit;\n        mMasterView.setDigits(mDigit);\n        mMinorView.setDigits(mDigit);\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/KViewListener.java",
    "content": "package com.tophold.trade.view.kview;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/04/04 18:12\n * 描 述 ：\n * ============================================================\n */\npublic class KViewListener {\n    /**\n     * 主图的长按、加载更多回调\n     */\n    public interface MasterTouchListener {\n        void onLongTouch(Quotes preQuotes, Quotes currentQuotes);\n\n        void onUnLongTouch();\n\n        void needLoadMore();\n    }\n\n    /**\n     * 主图的监听，主要供副图使用，把这些数据回调给副图，避免副图再做复杂重复的操作。\n     */\n    public interface MinorListener {\n        /**\n         * 长按操作\n         *\n         * @param pressIndex 按下所对应的索引\n         * @param currQuotes 按下所对应的点\n         */\n        void masterLongPressListener(int pressIndex, Quotes currQuotes);\n\n        /**\n         * 不再长按回调\n         */\n        void masterNoLongPressListener();\n\n        /**\n         * 缩放\n         *\n         * @param beginIndex    缩放后的起始位置索引\n         * @param endIndex      缩放后的结束索引\n         * @param shownMaxCount 可见数据总条数\n         */\n        void masteZoomlNewIndex(int beginIndex, int endIndex, int shownMaxCount);\n\n        /**\n         * 左右滑动\n         *\n         * @param endIndex      滑动后的结束索引\n         * @param currPullType  当前PullType类型\n         * @param shownMaxCount\n         * @param shownMaxCount 可见数据总条数\n         */\n        void mastelPullmNewIndex(int beginIndex, int endIndex, KViewType.PullType currPullType, int shownMaxCount);\n\n    }\n\n    /**\n     * 关键点的监听：可视范围内最大值点、可视范围内最小值点、最后一个点监听（数据集合的最后一个点）\n     */\n    public interface PostionListner {\n        void postion(Quotes quotes, float x, float y);\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/KViewType.java",
    "content": "package com.tophold.trade.view.kview;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/04/04 17:04\n * 描 述 ：\n * ============================================================\n */\npublic class KViewType {\n    /**\n     * 主图类型：分时图还是蜡烛图\n     */\n    public enum MasterViewType {\n        TIMESHARING,\n        CANDLE\n    }\n\n    /**\n     * 拖拽类型\n     */\n    protected enum PullType {\n        PULL_RIGHT,//向右滑动\n        PULL_LEFT,//向左滑动\n        PULL_RIGHT_STOP,//滑动到最右边\n        PULL_LEFT_STOP,//滑动到最左边\n    }\n\n    /**\n     * 主图上面的技术指标类型\n     */\n    public enum MasterIndicatrixType {\n        NONE,//无\n        MA,//MA5、10、20\n        BOLL,//BOLL(26)\n        MA_BOLL//MA5、10、20和BOLL(26)同时展示\n    }\n\n\n    /**\n     * 主图上面的详细技术指标类型，主要用于判断何种具体的线，进行相应的处理\n     */\n    public enum MasterIndicatrixDetailType {\n        MA5,\n        MA10,\n        MA20,\n        BOLLUP,\n        BOLLMB,\n        BOLLDN\n    }\n\n    /**\n     * 副图上面的技术指标类型\n     */\n    public enum MinorIndicatrixType {\n        MACD,\n        RSI,\n        KDJ\n    }\n\n    /**\n     * 滑动的类型\n     */\n    public enum MoveType {\n        STEP,//一点一点移动\n        ONFLING//具有onfling效果\n    }\n\n    /**\n     * MA类型：主图：ma5,ma10,ma20;量图：ma5,ma10\n     */\n    public enum MaType {\n        ma5,//主图ma5\n        ma10,//主图ma10\n        ma20,//主图ma20\n        volMa5,//量图ma5\n        volMa10//量图ma10\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/MasterView.java",
    "content": "package com.tophold.trade.view.kview;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.DashPathEffect;\nimport android.graphics.Paint;\nimport android.graphics.Path;\nimport android.graphics.RectF;\nimport android.support.annotation.Nullable;\nimport android.support.v4.view.GestureDetectorCompat;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.GestureDetector;\nimport android.view.MotionEvent;\nimport android.view.ScaleGestureDetector;\n\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Locale;\n\nimport com.tophold.trade.Constant;\nimport com.tophold.trade.R;\nimport com.tophold.trade.utils.FormatUtil;\nimport com.tophold.trade.utils.ScreenUtils;\nimport com.tophold.trade.utils.TimeUtils;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更细日期 ：2018/01/14 12:03\n * 描 述 ：主图。该View可以实现绘制分时图和蜡烛图。通过void setViewType(KViewType.MasterViewType viewType)方法控制，该方法暴漏给使用者。\n * 为了模拟真实环境，拿到的数据没有直接使用，而是做了适配转换处理。没有使用任何第三方框架，\n * rx的使用仅仅在模拟网络环境获取数据的时候进行了线程的切换处理，控件中并没有使用。\n * <p>\n * 现功能如下：\n * 基础部分：绘制必要的各种背景、实时价横线显示、实时价更新、\n * 长按显示当前（距离按下点最近的有效点）价，并回调有效点、支持拖拽、支持缩放、支持加载更多、\n * 长按下不可滑动、滑动覆盖右侧内边距。\n * 分时图：加载分时折线图。\n * 蜡烛图：加载蜡烛图、主图指标：MA、BOLL、MA/BOLL。\n * <p>\n * 待完成：\n * 1. 代码结构命名优化\n * 2. 以动画形式加载分时折线图（入场时的动画，可以参考mpchart的效果）\n * 3. 拖拽支持onFiling、\n * <p>\n * 疑问：\n * 1. 对于每次更新数据或者拖动必须要更新整个绘制过程，是否有更好的解决方案？\n * 2. 是否可以封装成灵活的组件供开发者使用？如何封装？（属性、功能、交互比较多）\n * <p>\n * ============================================================\n **/\npublic class MasterView extends KBaseView {\n\n    /**\n     * 各种画笔及其参数\n     */\n\n    //画笔:折线图\n    Paint mBrokenLinePaint;\n    float mBrokenLineWidth = 2;\n    int mBrokenLineColor;\n    //是否是虚线。可更改\n    boolean mIsBrokenLineDashed = false;\n\n    //画笔:折线图阴影,折线图阴影的处理方式采用一个画笔两个Path进行处理\n    Paint mBrokenLineBgPaint;\n    //折线下面的浅蓝色\n    int mBrokenLineBgColor;\n    //透明度，可更改\n    int mBrokenLineBgAlpha = 40;\n\n    //画笔:最后一个小圆点的半径。对于是否显示小圆点，根据PullType.PULL_RIGHT_STOP判断\n    Paint mDotPaint;\n    float mDotRadius = 6;\n    int mDotColor;\n\n    //画笔:实时横线，这里的处理思路：记录最后一个点的位置坐标即可，从该点开始画小圆点、横线以及右侧实时数据\n    Paint mTimingLinePaint;\n    float mTimingLineWidth = 2;\n    int mTimingLineColor;\n    //是否是虚线，可更改\n    boolean mIsTimingLineDashed = true;\n\n    //画笔:实时横线右侧的红色的框和实时数据\n    Paint mTimingTxtBgPaint;//实时数据的背景\n    Paint mTimingTxtPaint;//实时数据\n    float mTimingTxtWidth = 18;\n    int mTimingTxtColor;\n    int mTimingTxtBgColor;\n\n    //画笔:长按十字的上方的时间框、右侧的数据框\n    Paint mLongPressTxtPaint;\n    Paint mLongPressTxtBgPaint;\n    int mLongPressTxtColor;\n    float mLongPressTxtSize = 18;\n    int mLongPressTxtBgColor;\n\n    /**\n     * 蜡烛图相关逻辑，思路：遍历找到可视范围内最大的high价格A（也就是可视范围内o、c、h、l四个值的最大值）和最小的low值B。\n     * 这个时候要重新计算y轴的均分值、在model中的floatY也要重新计算。(因为最大最小值变了，之前计算用的是可视范围内的最大和最小close价格)。\n     * <p>\n     * x轴单元大小：View有效宽度C（除去左右间距）,可视范围内数据数D,x轴单元大小（单个蜡烛宽度）E=C/D。\n     * y轴单元大小：View有效的高度F,y轴单元大小G=F/(A-B);\n     * <p>\n     * 单个蜡烛y轴的确认：蜡烛的y轴上下边的确认是根据open(H,开盘价,数据model中对应o)和close（I,收盘价，对应c）确认。\n     * View下边距K,总高度L，单个蜡烛的开盘价对应的y轴坐标J=L-((H-B)*G+K);另一边亦然。\n     * <p>\n     * 颜色的确认：至于哪个在上哪个在下看大小。大的在上面，小的在下面。同时，收盘价大于开盘价，蜡烛图为红色。反之，亦然。\n     */\n    //画笔:\n    Paint mCandlePaint;\n    int mRedCandleColor;\n    int mGreenCandleColor;\n    int mEqualCandleColor;//y轴开盘价和收盘价一致时设置的颜色\n    //单个蜡烛最大值最小值对应的y轴方向的线宽度\n    int mCanldeHighLowWidth = 1;\n    //指标类型\n    KViewType.MasterIndicatrixType mMasterType = KViewType.MasterIndicatrixType.NONE;\n\n    //MA\n    Paint mMa5Paint;\n    int mMa5Color;\n    Paint mMa10Paint;\n    int mMa10Color;\n    Paint mMa20Paint;\n    int mMa20Color;\n\n\n    //BOLL\n    Paint mBollUpPaint;\n    int mBollUpColor;\n    Paint mBollMbPaint;\n    int mBollMbColor;\n    Paint mBollDnPaint;\n    int mBollDnColor;\n\n    //最大值和最小值\n    Paint mMinMaxPaint;\n    int mMinMaxColor;\n\n    //view类型：是分时图还是蜡烛图\n    protected KViewType.MasterViewType mViewType = KViewType.MasterViewType.TIMESHARING;\n\n    /**\n     * 绘制蜡烛图：y轴，可以根据可视范围内的最大high值（A）和最小low值（B）以及有效y轴高度（C）计算出\n     * 单位高度mPerY(D),D=C/(A-B)。\n     * x轴暂时直接先取mPerX作为宽度，不留间隙。\n     * 那么，蜡烛图就可以根据当前位置的high、low两个值绘制最大最小值；\n     * 然后根据open和close绘制蜡烛图的上起点和下结束点。\n     * 至于颜色，当当前值为的Quote的close大于open,为红色；反之为绿色。\n     */\n    //根据可见范围内最大的high价格和最小的low价格计算的y单位长度。该参数父类已经定义。\n    //protected float mPerY;\n    /**\n     * 蜡烛图：整个视图的最大值和最小值（y轴边界值），不管视图中是分时图、蜡烛图（以及蜡烛图中的指标）必须找到上下边界，\n     * 然后根据该边界值会绘制，不然会出现绘制超过边界的情况。特别明显的一种情况：蜡烛图模式下，存在不存在BOLL线，\n     * 蜡烛的高度显示是不一样的，因为一般情况下BOLL的上边界会比蜡烛图大。\n     */\n    protected double mCandleMinY;\n    protected double mCandleMaxY;\n    //蜡烛图间隙，大小以单个蜡烛图的宽度的比例算。可修改。\n    protected float mCandleDiverWidthRatio = 0.1f;\n\n    //持有副图长按，方便监听\n    private KViewListener.MinorListener mMinorListener;\n    //持有量图长按，方便监听\n    private KViewListener.MinorListener mVolListener;\n\n    //最大值监听\n    private KViewListener.PostionListner mMaxPostionListener;\n    //最小值监听\n    private KViewListener.PostionListner mMinPostionListener;\n    //最后一个数据的位置监听\n    private KViewListener.PostionListner mLastPostionListener;\n\n    public void setMinorListener(KViewListener.MinorListener minorListener) {\n        mMinorListener = minorListener;\n    }\n\n    public KViewListener.MinorListener getVolListener() {\n        return mVolListener;\n    }\n\n    public MasterView setVolListener(KViewListener.MinorListener volListener) {\n        mVolListener = volListener;\n        return this;\n    }\n\n    public KViewListener.PostionListner getMaxPostionListener() {\n        return mMaxPostionListener;\n    }\n\n    public MasterView setMaxPostionListener(KViewListener.PostionListner maxPostionListener) {\n        mMaxPostionListener = maxPostionListener;\n        return this;\n    }\n\n    public KViewListener.PostionListner getMinPostionListener() {\n        return mMinPostionListener;\n    }\n\n    public MasterView setMinPostionListener(KViewListener.PostionListner minPostionListener) {\n        mMinPostionListener = minPostionListener;\n        return this;\n    }\n\n    public KViewListener.PostionListner getLastPostionListener() {\n        return mLastPostionListener;\n    }\n\n    public MasterView setLastPostionListener(KViewListener.PostionListner lastPostionListener) {\n        mLastPostionListener = lastPostionListener;\n        return this;\n    }\n\n    public MasterView(Context context) {\n        this(context, null);\n    }\n\n    public MasterView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public MasterView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initAttrs();\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n        super.onLayout(changed, left, top, right, bottom);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        if (mQuotesList == null || mQuotesList.isEmpty()) {\n            return;\n        }\n        //绘制x周和y周的文字\n        drawXyTxt(canvas);\n\n        /**\n         * 将需要遍历可视范围内的数据的操作全部在这里处理，尽可能少的遍历数据次数。\n         * 现在处理的如下：分时图折现、蜡烛图、实时横线、长按十字。\n         */\n        drawLooper(canvas);\n\n        //绘制主图上的指标\n        drawMasterLegend(canvas);\n        drawMasterIndicatrix(canvas);\n    }\n\n    protected void initAttrs() {\n        //加载颜色和字符串资源\n        loadDefAttrs();\n\n        //初始化画笔\n        initDotPaint();\n        initTimingTxtPaint();\n        initTimingLinePaint();\n        initLongPressTxtPaint();\n        initBrokenLinePaint();\n        initBrokenLineBgPaint();\n        initCandlePaint();\n        initMaPaint();\n        initBollPaint();\n        initMinMaxPaint();\n\n        //手势\n        mScaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);\n\n        mFlingDetector = new GestureDetectorCompat(mContext, mSimpleOnScaleGestureListener);\n        mFlingDetector.setIsLongpressEnabled(false);\n\n\n        //是分时图还是蜡烛图,def\n        setViewType(KViewType.MasterViewType.TIMESHARING);\n        //底部距离\n        mBasePaddingBottom = 35;\n\n        setMoveType(KViewType.MoveType.STEP);\n    }\n\n    private void initMinMaxPaint() {\n        mMinMaxPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mMinMaxPaint.setColor(mMinMaxColor);\n        mMinMaxPaint.setStyle(Paint.Style.FILL);\n        mMinMaxPaint.setTextSize(16);\n\n    }\n\n    @Override\n    public boolean onTouchEvent(MotionEvent event) {\n        mScaleGestureDetector.onTouchEvent(event);\n        if (mMoveType == KViewType.MoveType.ONFLING) {\n            mFlingDetector.onTouchEvent(event);\n        }\n        return super.onTouchEvent(event);\n    }\n\n    protected void loadDefAttrs() {\n        //数据源\n        mQuotesList = new ArrayList<>(mShownMaxCount);\n        //颜色\n        mBrokenLineColor = getColor(R.color.color_timeSharing_brokenLineColor);\n        mDotColor = getColor(R.color.color_timeSharing_dotColor);\n        mTimingLineColor = getColor(R.color.color_timeSharing_timingLineColor);\n        mBrokenLineBgColor = getColor(R.color.color_timeSharing_blowBlueColor);\n        mTimingTxtColor = getColor(R.color.color_timeSharing_timingTxtColor);\n        mTimingTxtBgColor = getColor(R.color.color_timeSharing_timingTxtBgColor);\n        mLongPressTxtColor = getColor(R.color.color_timeSharing_longPressTxtColor);\n        mLongPressTxtBgColor = getColor(R.color.color_timeSharing_longPressTxtBgColor);\n        mRedCandleColor = getColor(R.color.color_timeSharing_candleRed);\n        mGreenCandleColor = getColor(R.color.color_timeSharing_candleGreen);\n        mEqualCandleColor = getColor(R.color.color_timeSharing_candleEqual);\n\n        mMa5Color = getColor(R.color.color_masterView_ma5Color);\n        mMa10Color = getColor(R.color.color_masterView_ma10Color);\n        mMa20Color = getColor(R.color.color_masterView_ma20Color);\n\n        mBollUpColor = getColor(R.color.color_masterView_bollUpColor);\n        mBollMbColor = getColor(R.color.color_masterView_bollMbColor);\n        mBollDnColor = getColor(R.color.color_masterView_bollDnColor);\n\n        mMinMaxColor = getColor(R.color.color_minmax);\n    }\n\n    protected void initDotPaint() {\n        mDotPaint = new Paint();\n        mDotPaint.setColor(mDotColor);\n        mDotPaint.setStyle(Paint.Style.FILL);\n        mDotPaint.setAntiAlias(true);\n    }\n\n    protected void initTimingTxtPaint() {\n        mTimingTxtBgPaint = new Paint();\n        mTimingTxtBgPaint.setColor(mTimingTxtBgColor);\n        mTimingTxtBgPaint.setAntiAlias(true);\n\n        mTimingTxtPaint = new Paint();\n        mTimingTxtPaint.setTextSize(mTimingTxtWidth);\n        mTimingTxtPaint.setColor(mTimingTxtColor);\n        mTimingTxtPaint.setAntiAlias(true);\n    }\n\n    protected void initTimingLinePaint() {\n        mTimingLinePaint = new Paint();\n        mTimingLinePaint.setColor(mTimingLineColor);\n        mTimingLinePaint.setStrokeWidth(mTimingLineWidth);\n        mTimingLinePaint.setStyle(Paint.Style.STROKE);\n        mTimingLinePaint.setAntiAlias(true);\n        if (mIsTimingLineDashed) {\n            setLayerType(LAYER_TYPE_SOFTWARE, null);\n            mTimingLinePaint.setPathEffect(new DashPathEffect(new float[]{8, 8}, 0));\n        }\n    }\n\n    protected void initLongPressTxtPaint() {\n        mLongPressTxtPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mLongPressTxtPaint.setTextSize(mLongPressTxtSize);\n        mLongPressTxtPaint.setColor(mLongPressTxtColor);\n\n        mLongPressTxtBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mLongPressTxtBgPaint.setColor(mLongPressTxtBgColor);\n    }\n\n    protected void initBrokenLinePaint() {\n        mBrokenLinePaint = new Paint();\n        mBrokenLinePaint.setColor(mBrokenLineColor);\n        mBrokenLinePaint.setStrokeWidth(mBrokenLineWidth);\n        mBrokenLinePaint.setStyle(Paint.Style.STROKE);\n        mBrokenLinePaint.setAntiAlias(true);\n\n        if (mIsBrokenLineDashed) {\n            setLayerType(LAYER_TYPE_SOFTWARE, null);\n            mBrokenLinePaint.setPathEffect(new DashPathEffect(new float[]{5, 5}, 0));\n        }\n    }\n\n    protected void initBrokenLineBgPaint() {\n        mBrokenLineBgPaint = new Paint();\n        mBrokenLineBgPaint.setColor(mBrokenLineBgColor);\n        mBrokenLineBgPaint.setStyle(Paint.Style.FILL);\n        mBrokenLineBgPaint.setAntiAlias(true);\n        mBrokenLineBgPaint.setAlpha(mBrokenLineBgAlpha);\n    }\n\n    private void initCandlePaint() {\n        mCandlePaint = new Paint();\n        mCandlePaint.setColor(mRedCandleColor);\n        mCandlePaint.setStyle(Paint.Style.FILL);\n        mCandlePaint.setAntiAlias(true);\n        mCandlePaint.setStrokeWidth(mCanldeHighLowWidth);\n    }\n\n    private void initMaPaint() {\n        mMa5Paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mMa5Paint.setColor(mMa5Color);\n        mMa5Paint.setStyle(Paint.Style.STROKE);\n        mMa5Paint.setStrokeWidth(mLineWidth);\n        mMa5Paint.setTextSize(mLegendTxtSize);\n\n        mMa10Paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mMa10Paint.setColor(mMa10Color);\n        mMa10Paint.setStyle(Paint.Style.STROKE);\n        mMa10Paint.setStrokeWidth(mLineWidth);\n        mMa10Paint.setTextSize(mLegendTxtSize);\n\n        mMa20Paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mMa20Paint.setColor(mMa20Color);\n        mMa20Paint.setStyle(Paint.Style.STROKE);\n        mMa20Paint.setStrokeWidth(mLineWidth);\n        mMa20Paint.setTextSize(mLegendTxtSize);\n    }\n\n    private void initBollPaint() {\n        mBollMbPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mBollMbPaint.setColor(mBollMbColor);\n        mBollMbPaint.setStyle(Paint.Style.STROKE);\n        mBollMbPaint.setStrokeWidth(mLineWidth);\n        mBollMbPaint.setTextSize(mLegendTxtSize);\n\n\n        mBollUpPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mBollUpPaint.setColor(mBollUpColor);\n        mBollUpPaint.setStyle(Paint.Style.STROKE);\n        mBollUpPaint.setStrokeWidth(mLineWidth);\n        mBollUpPaint.setTextSize(mLegendTxtSize);\n\n\n        mBollDnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mBollDnPaint.setColor(mBollDnColor);\n        mBollDnPaint.setStyle(Paint.Style.STROKE);\n        mBollDnPaint.setStrokeWidth(mLineWidth);\n        mBollDnPaint.setTextSize(mLegendTxtSize);\n\n    }\n\n    protected void drawXyTxt(Canvas canvas) {\n        //先处理y轴方向文字\n        drawYPaint(canvas);\n\n        //处理x轴方向文字\n        drawXPaint(canvas);\n    }\n\n    private void drawLooper(Canvas canvas) {\n        Quotes firstQ = mQuotesList.get(mBeginIndex);\n\n\n        /**分时图折现的绘制*/\n        Path brokenLinePath = new Path();\n        Path brokenLineBgPath = new Path();\n\n        /**实时横线的绘制*/\n        drawTimingLineProcess(canvas, mQuotesList.get(mQuotesList.size() - 1));\n\n        /**蜡烛图的绘制*/\n        //蜡烛图单个之间的间隙\n        float diverWidth = mCandleDiverWidthRatio * mPerX;\n\n        /**长按的绘制*/\n        //最后的最近的按下的位置\n        int finalIndex = mBeginIndex;\n        //获取距离最近按下的位置的model\n        float pressX = mMovingX;\n        //循环遍历，找到距离最短的x轴的mode\n        Quotes finalFundMode = firstQ;\n        //遍历的点距离按下的距离\n        float minXLen = Integer.MAX_VALUE;\n\n        //寻找可视范围内的最大值和最小值\n        double maxClose = Integer.MIN_VALUE;\n        double minClose = Integer.MAX_VALUE;\n        int maxIndex = -1;\n        int minIndex = -1;\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n            //mPerX/2.0f：为了让取点为单个单元的x的中间位置\n            float floatX = getFloatX(i);\n            float floatY = getFloatY((float) quotes.c);\n\n\n            //记录下位置信息\n            quotes.floatX = floatX;\n            quotes.floatY = floatY;\n\n\n            /**确认最大值和最小值*/\n            if (quotes.h > maxClose) {\n                maxClose = quotes.h;\n                maxIndex = i;\n            }\n            if (quotes.l < minClose) {\n                minClose = quotes.l;\n                minIndex = i;\n            }\n\n\n            /**分时图折现的绘制*/\n            drawTimSharingProcess(quotes, i, brokenLinePath, brokenLineBgPath);\n\n            /**蜡烛图的绘制*/\n            drawCandleViewProcess(canvas, diverWidth, i, quotes);\n\n            /**长按的绘制*/\n            if (mDrawLongPress) {\n                float abs = Math.abs(pressX - floatX);\n                if (abs < minXLen) {\n                    finalFundMode = quotes;\n                    minXLen = abs;\n                    finalIndex = i;\n                }\n            }\n\n        }\n        /**分时图折现的绘制*/\n        drawTimSharing(canvas, brokenLinePath, brokenLineBgPath);\n\n        /**长按的绘制*/\n        drawLongPress(canvas, finalIndex, finalFundMode);\n\n        /**回调最小值和最大值。注意：在分时图上不显示（为什么？）。*/\n        if (maxIndex != -1 && mViewType == KViewType.MasterViewType.CANDLE) {\n            Quotes quotes = mQuotesList.get(maxIndex);\n            float x = getFloatX(maxIndex);\n            float y = getFloatY((float) quotes.h);\n            if (mMaxPostionListener != null) mMaxPostionListener.postion(quotes, x, y);\n\n\n            y -= ScreenUtils.dip2px(10);\n            float xHeight = ScreenUtils.dip2px(15);\n            float posHalfX = getBaseWidth() / 2.0f;\n            String txt = FormatUtil.numFormat(quotes.h, mDigits);\n            float stopX = x > posHalfX ? x - xHeight : x + xHeight;\n            canvas.drawLine(x, y, stopX, y, mMinMaxPaint);\n            x = stopX;\n            if (x > posHalfX) {\n                x -= mMinMaxPaint.measureText(txt);\n            }\n            y += getFontHeight(mMinMaxPaint.getTextSize(), mMinMaxPaint) / 4.0f;\n            canvas.drawText(txt, x, y, mMinMaxPaint);\n        }\n        if (minIndex != -1 && mViewType == KViewType.MasterViewType.CANDLE) {\n            Quotes quotes = mQuotesList.get(minIndex);\n            float x = getFloatX(minIndex);\n            float y = getFloatY((float) quotes.l);\n            if (mMinPostionListener != null) mMinPostionListener.postion(quotes, x, y);\n\n            y += ScreenUtils.dip2px(10);\n            float xHeight = ScreenUtils.dip2px(15);\n            float posHalfX = getBaseWidth() / 2.0f;\n            String txt = FormatUtil.numFormat(quotes.l, mDigits);\n            float stopX = x > posHalfX ? x - xHeight : x + xHeight;\n            canvas.drawLine(x, y, stopX, y, mMinMaxPaint);\n            x = stopX;\n            if (x > posHalfX) {\n                x -= mMinMaxPaint.measureText(txt);\n            }\n            y += getFontHeight(mMinMaxPaint.getTextSize(), mMinMaxPaint) / 4.0f;\n            canvas.drawText(txt, x, y, mMinMaxPaint);\n        }\n\n    }\n\n    private float getFloatY(float price) {\n        return (float) (mBaseHeight - mBasePaddingBottom - mInnerBottomBlankPadding -\n                mPerY * (price - mCandleMinY));\n    }\n\n    private float getFloatX(int i) {\n        return mBasePaddingLeft + mPerX / 2.0f + mPerX * (i - mBeginIndex);\n    }\n\n    private void drawMasterLegend(Canvas canvas) {\n        if (mViewType != KViewType.MasterViewType.CANDLE) return;\n\n        //长按\n        if (mDrawLongPress) {\n            if (mCurrLongPressQuotes == null) return;\n            mMa5Paint.setStyle(Paint.Style.FILL);\n            mMa10Paint.setStyle(Paint.Style.FILL);\n            mMa20Paint.setStyle(Paint.Style.FILL);\n            mBollDnPaint.setStyle(Paint.Style.FILL);\n            mBollUpPaint.setStyle(Paint.Style.FILL);\n            mBollMbPaint.setStyle(Paint.Style.FILL);\n            String showTxt = \"\";\n            if (mMasterType == KViewType.MasterIndicatrixType.MA) {\n                showTxt = \"• MA5 \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.ma5, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mMa5Paint);\n\n                float leftWidth = mMa5Paint.measureText(showTxt);\n                showTxt = \"• MA10 \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.ma10, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft + leftWidth),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mMa10Paint);\n\n                float leftWidth2 = mMa10Paint.measureText(showTxt);\n                showTxt = \"• MA20 \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.ma20, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft + leftWidth + leftWidth2),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mMa20Paint);\n            } else if (mMasterType == KViewType.MasterIndicatrixType.BOLL) {\n                showTxt = \"• UPPER \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.up, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mBollMbPaint);\n\n                float leftWidth = mBollMbPaint.measureText(showTxt);\n                showTxt = \"• MID \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.mb, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft + leftWidth),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mBollUpPaint);\n\n                float leftWidth2 = mBollUpPaint.measureText(showTxt);\n                showTxt = \"• LOWER \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.dn, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft + leftWidth + leftWidth2),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mBollDnPaint);\n\n            } else if (mMasterType == KViewType.MasterIndicatrixType.MA_BOLL) {\n                showTxt = \"• MA5 \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.ma5, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mMa5Paint);\n\n                float leftWidth = mMa5Paint.measureText(showTxt);\n                showTxt = \"• MA10 \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.ma10, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft + leftWidth),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mMa10Paint);\n\n                float leftWidth2 = mMa10Paint.measureText(showTxt);\n                showTxt = \"• MA20 \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.ma20, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft + leftWidth + leftWidth2),\n                        (float) (mLegendPaddingTop + mBasePaddingTop), mMa20Paint);\n\n\n                double high = getFontHeight(mLegendTxtSize, mMa5Paint);\n                high += mLegendTxtTopPadding;\n                showTxt = \"• UPPER \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.mb, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft),\n                        (float) (mLegendPaddingTop + mBasePaddingTop + high), mBollMbPaint);\n\n                float leftWidth3 = mBollMbPaint.measureText(showTxt);\n                showTxt = \"• MID \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.up, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft + leftWidth3),\n                        (float) (mLegendPaddingTop + mBasePaddingTop + high), mBollUpPaint);\n\n                float leftWidth23 = mBollUpPaint.measureText(showTxt);\n                showTxt = \"• LOWER \" + FormatUtil.formatBySubString(mCurrLongPressQuotes.dn, mDigits) + \" \";\n                canvas.drawText(showTxt, (float) (mLegendPaddingLeft + mBasePaddingLeft + leftWidth23 + leftWidth3),\n                        (float) (mLegendPaddingTop + mBasePaddingTop + high), mBollDnPaint);\n\n            }\n        } else {\n            //非长按\n            String showTxt = \"\";\n            if (mMasterType == KViewType.MasterIndicatrixType.MA) {\n                showTxt = \"MA(5,10,20)\";\n            } else if (mMasterType == KViewType.MasterIndicatrixType.BOLL) {\n                showTxt = \"BOLL(26)\";\n\n            } else if (mMasterType == KViewType.MasterIndicatrixType.MA_BOLL) {\n                showTxt = \"BOLL(26)&MA(5,10,20)\";\n            }\n            canvas.drawText(showTxt,\n                    (float) (mBaseWidth - mLegendPaddingRight - mBasePaddingRight - mLegendPaint.measureText(showTxt)),\n                    (float) (mLegendPaddingTop + mBasePaddingTop), mLegendPaint);\n        }\n    }\n\n    private void drawMasterIndicatrix(Canvas canvas) {\n        //指标展示的前提是蜡烛图\n        if (mViewType != KViewType.MasterViewType.CANDLE) return;\n\n        if (mMasterType == KViewType.MasterIndicatrixType.NONE) {\n\n        } else if (mMasterType == KViewType.MasterIndicatrixType.MA) {\n            drawMa(canvas);\n        } else if (mMasterType == KViewType.MasterIndicatrixType.BOLL) {\n            drawBoll(canvas);\n        } else if (mMasterType == KViewType.MasterIndicatrixType.MA_BOLL) {\n            drawMa(canvas);\n            drawBoll(canvas);\n        }\n\n    }\n\n    private void drawMa(Canvas canvas) {\n        mMa5Paint.setStyle(Paint.Style.STROKE);\n        mMa10Paint.setStyle(Paint.Style.STROKE);\n        mMa20Paint.setStyle(Paint.Style.STROKE);\n\n        Path path5 = new Path();\n        Path path10 = new Path();\n        Path path20 = new Path();\n        boolean isFirstMa5 = true;\n        boolean isFirstMa10 = true;\n        boolean isFirstMa20 = true;\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n            //在绘制蜡烛图的时候已经计算了\n            float floatX = quotes.floatX;\n\n            float floatY = getMasterDetailFloatY(quotes, KViewType.MasterIndicatrixDetailType.MA5);\n\n            //异常,在View的行为就是不显示而已，影响不大。一般都是数据的开头部分。\n            if (floatY == -1) continue;\n\n            if (isFirstMa5) {\n                isFirstMa5 = false;\n                path5.moveTo(floatX, floatY);\n            } else {\n                path5.lineTo(floatX, floatY);\n            }\n\n            floatY = getMasterDetailFloatY(quotes, KViewType.MasterIndicatrixDetailType.MA10);\n\n            //异常\n            if (floatY == -1) continue;\n\n            if (isFirstMa10) {\n                isFirstMa10 = false;\n                path10.moveTo(floatX, floatY);\n            } else {\n                path10.lineTo(floatX, floatY);\n            }\n\n            floatY = getMasterDetailFloatY(quotes, KViewType.MasterIndicatrixDetailType.MA20);\n\n            //异常\n            if (floatY == -1) continue;\n\n            if (isFirstMa20) {\n                isFirstMa20 = false;\n                path20.moveTo(floatX, floatY);\n            } else {\n                path20.lineTo(floatX, floatY);\n            }\n        }\n\n        canvas.drawPath(path5, mMa5Paint);\n        canvas.drawPath(path10, mMa10Paint);\n        canvas.drawPath(path20, mMa20Paint);\n    }\n\n    private float getMasterDetailFloatY(Quotes quotes, KViewType.MasterIndicatrixDetailType maType) {\n        double v = 0;\n        //ma\n        if (maType == KViewType.MasterIndicatrixDetailType.MA5) {\n            v = quotes.ma5 - mCandleMinY;\n        } else if (maType == KViewType.MasterIndicatrixDetailType.MA10) {\n            v = quotes.ma10 - mCandleMinY;\n        } else if (maType == KViewType.MasterIndicatrixDetailType.MA20) {\n            v = quotes.ma20 - mCandleMinY;\n        }\n        //boll\n        else if (maType == KViewType.MasterIndicatrixDetailType.BOLLUP) {\n            v = quotes.up - mCandleMinY;\n        } else if (maType == KViewType.MasterIndicatrixDetailType.BOLLMB) {\n            v = quotes.mb - mCandleMinY;\n        } else if (maType == KViewType.MasterIndicatrixDetailType.BOLLDN) {\n            v = quotes.dn - mCandleMinY;\n        }\n        //异常，当不存在ma值时的处理.也就是up、mb、dn为0时，这样判断其实有问题，比如算出来的值就是0？？？\n        if (v + mCandleMinY == 0) return -1;\n\n        double h = v * mPerY;\n        float y = (float) (mBaseHeight - h - mBasePaddingBottom - mInnerBottomBlankPadding);\n\n        //这里的y,存在一种情况，y超过了View的上边界或者超过了下边界，当出现这一种情况时，不显示，当作异常情况\n        if (y < mBasePaddingTop || y > mBaseHeight - mBasePaddingBottom)\n            return -1;\n\n        return y;\n    }\n\n    private void drawBoll(Canvas canvas) {\n        mBollDnPaint.setStyle(Paint.Style.STROKE);\n        mBollUpPaint.setStyle(Paint.Style.STROKE);\n        mBollMbPaint.setStyle(Paint.Style.STROKE);\n\n        Path mbPath = new Path();\n        Path upPath = new Path();\n        Path dnPath = new Path();\n        boolean isFirstMB = true;\n        boolean isFirstUP = true;\n        boolean isFirstDN = true;\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n            float floatX = quotes.floatX;//在绘制蜡烛图的时候已经计算了\n\n            //上轨线\n            float floatY = getMasterDetailFloatY(quotes, KViewType.MasterIndicatrixDetailType.BOLLUP);\n            //异常\n            if (floatY == -1) continue;\n\n            if (isFirstUP) {\n                isFirstUP = false;\n                upPath.moveTo(floatX, floatY);\n            } else {\n                upPath.lineTo(floatX, floatY);\n            }\n\n            //中轨线\n            floatY = getMasterDetailFloatY(quotes, KViewType.MasterIndicatrixDetailType.BOLLMB);\n            //异常,在View的行为就是不显示而已，影响不大。一般都是数据的开头部分。\n            if (floatY == -1) continue;\n\n            if (isFirstMB) {\n                isFirstMB = false;\n                mbPath.moveTo(floatX, floatY);\n            } else {\n                mbPath.lineTo(floatX, floatY);\n            }\n\n\n            //下轨线\n            floatY = getMasterDetailFloatY(quotes, KViewType.MasterIndicatrixDetailType.BOLLDN);\n            //异常\n            if (floatY == -1) continue;\n\n            if (isFirstDN) {\n                isFirstDN = false;\n                dnPath.moveTo(floatX, floatY);\n            } else {\n                dnPath.lineTo(floatX, floatY);\n            }\n        }\n\n        canvas.drawPath(upPath, mBollUpPaint);\n        canvas.drawPath(mbPath, mBollMbPaint);\n        canvas.drawPath(dnPath, mBollDnPaint);\n    }\n\n    /**\n     * 绘制蜡烛图\n     *\n     * @param canvas\n     * @param diverWidth 蜡烛图之间的间距\n     * @param i          List index\n     * @param quotes     目标Quotes\n     */\n    private void drawCandleViewProcess(Canvas canvas, float diverWidth, int i, Quotes quotes) {\n        if (mViewType != KViewType.MasterViewType.CANDLE) return;\n\n        float topRectY;\n        float bottomRectY;\n        float leftRectX;\n        float rightRectX;\n        float leftLineX;\n        float topLineY;\n        float rightLineX;\n        float bottomLineY;\n        //定位蜡烛矩形的四个点\n        topRectY = (float) (mBasePaddingTop + mInnerTopBlankPadding +\n                mPerY * (mCandleMaxY - quotes.o));\n        bottomRectY = (float) (mBasePaddingTop + mInnerTopBlankPadding +\n                mPerY * (mCandleMaxY - quotes.c));\n        leftRectX = -mPerX / 2 + quotes.floatX + diverWidth / 2;\n        rightRectX = mPerX / 2 + quotes.floatX - diverWidth / 2;\n\n        //定位单个蜡烛中间线的四个点\n        leftLineX = quotes.floatX;\n        topLineY = (float) (mBasePaddingTop + mInnerTopBlankPadding +\n                mPerY * (mCandleMaxY - quotes.h));\n        rightLineX = quotes.floatX;\n        bottomLineY = (float) (mBasePaddingTop + mInnerTopBlankPadding +\n                mPerY * (mCandleMaxY - quotes.l));\n\n        RectF rectF = new RectF();\n\n        int renderColor;\n        //细化渲染值\n        if (quotes.c > quotes.o) {\n            renderColor = mRedCandleColor;\n        } else if (quotes.c < quotes.o) {\n            renderColor = mGreenCandleColor;\n        } else {\n            //上下边界一样，设置一个偏移值\n            if (topRectY == bottomRectY) bottomRectY += dp2px(1f);\n            renderColor = mEqualCandleColor;\n        }\n\n        rectF.set(leftRectX, topRectY, rightRectX, bottomRectY);\n        //设置颜色\n        mCandlePaint.setColor(renderColor);\n        canvas.drawRect(rectF, mCandlePaint);\n\n        //开始画low、high线\n        canvas.drawLine(leftLineX, topLineY, rightLineX, bottomLineY, mCandlePaint);\n    }\n\n    private void drawLongPress(Canvas canvas, int finalIndex, Quotes finalFundMode) {\n        if (!mDrawLongPress) return;\n\n        //x轴线\n        canvas.drawLine(mBasePaddingLeft, finalFundMode.floatY, mBaseWidth - mBasePaddingRight,\n                finalFundMode.floatY, mLongPressPaint);\n        //y轴线\n        canvas.drawLine(finalFundMode.floatX, mBasePaddingTop, finalFundMode.floatX,\n                mBaseHeight - mBasePaddingBottom, mLongPressPaint);\n\n        //将长按信息回调给副图，方便副图处理长按信息\n        if (mMinorListener != null)\n            mMinorListener.masterLongPressListener(finalIndex, finalFundMode);\n\n        if (mVolListener != null)\n            mVolListener.masterLongPressListener(finalIndex, finalFundMode);\n\n\n        //接着绘制长按上方和右侧文字信息背景\n        float txtBgHight = getFontHeight(mLongPressTxtSize, mLongPressTxtBgPaint);\n        //y\n        float longPressTxtYPadding = 10;\n        canvas.drawRect(finalFundMode.floatX -\n                        mLongPressTxtBgPaint.measureText(finalFundMode.getShowTime()) / 2 -\n                        longPressTxtYPadding,\n                mBasePaddingTop,\n                finalFundMode.floatX +\n                        mLongPressTxtBgPaint.measureText(finalFundMode.getShowTime()) / 2 +\n                        longPressTxtYPadding,\n                mBasePaddingTop + txtBgHight, mLongPressTxtBgPaint);\n        //x\n        //加一个左右边距\n        canvas.drawRect(mBaseWidth - mBasePaddingRight, finalFundMode.floatY - txtBgHight / 2,\n                mBaseWidth,\n                finalFundMode.floatY + txtBgHight / 2,\n                mLongPressTxtBgPaint);\n\n        //绘制长按上方和右侧文字信息\n        float txtHight = getFontHeight(mLongPressTxtSize, mLongPressTxtPaint);\n        //x\n        //距离左边的距离\n        float leftDis = 8;\n        canvas.drawText(FormatUtil.numFormat(finalFundMode.c, mDigits),\n                mBaseWidth - mBasePaddingRight + leftDis,\n                finalFundMode.floatY + txtHight / 4//这特么的又是需要+/4,理论应该是-/2,原因不明\n                , mLongPressTxtPaint);\n        //y\n        canvas.drawText(finalFundMode.getShowTime(),\n                finalFundMode.floatX - mLongPressTxtPaint.measureText(finalFundMode.getShowTime()) / 2,\n                mBasePaddingTop + txtHight - 6\n                , mLongPressTxtPaint);\n\n        //在这里回调数据信息\n        int size = mQuotesList.size();\n        if ((0 <= finalIndex && finalIndex < size) &&\n                (0 <= finalIndex - 1 && finalIndex - 1 < size))\n            //记录当前Quotes\n            mCurrLongPressQuotes = mQuotesList.get(finalIndex);\n        if (mMasterTouchListener != null) {\n            //回调,需要两个数据，便于计算涨跌百分比\n            mMasterTouchListener.onLongTouch(mQuotesList.get(finalIndex - 1),\n                    mQuotesList.get(finalIndex));\n        }\n    }\n\n    private void drawTimSharing(Canvas canvas, Path brokenLinePath, Path brokenLineBgPath) {\n        if (mViewType != KViewType.MasterViewType.TIMESHARING) return;\n\n        canvas.drawPath(brokenLinePath, mBrokenLinePaint);\n        canvas.drawPath(brokenLineBgPath, mBrokenLineBgPaint);\n    }\n\n    private void drawTimingLineProcess(Canvas canvas, Quotes quotes) {\n        //这里滑动到最右端\n        //绘制小圆点\n        if (mPullType == KViewType.PullType.PULL_RIGHT_STOP) {\n            //这里记录最后一个点的位置\n            float floatX = mBaseWidth - mInnerRightBlankPadding - mBasePaddingRight - mPerX / 2.0f;\n            float floatY = getFloatY((float) quotes.c);\n            quotes.floatX = floatX;\n            quotes.floatY = floatY;\n\n            //对于蜡烛图不需要绘制小圆点，但是需要绘制实时横线\n            if (mViewType == KViewType.MasterViewType.TIMESHARING) {\n                canvas.drawCircle(quotes.floatX, quotes.floatY, mDotRadius, mDotPaint);\n            }\n        } else {\n            //这里隐藏小圆点并且重新计算Y值。这里这样处理，对应现象的问题：横线划出界面。\n            Quotes endQuotes = mQuotesList.get(mQuotesList.size() - 1);\n\n            //蜡烛图\n            quotes.floatY = getFloatY((float) endQuotes.c);\n        }\n\n        /**\n         * 回调后注意处理边界问题\n         */\n        if (mLastPostionListener != null)\n            mLastPostionListener.postion(quotes, quotes.floatX, quotes.floatY);\n\n        //实时数据展示的前提是在指定范围内。不处理对应的异常：实时横线显示在底部横线的下面...\n        if (mBasePaddingTop < quotes.floatY && quotes.floatY < mBaseHeight - mBasePaddingBottom) {\n            //接着画实时横线\n            canvas.drawLine(mBasePaddingLeft, quotes.floatY, mBaseWidth - mBasePaddingRight, quotes.floatY,\n                    mTimingLinePaint);\n\n            //接着绘制实时横线的右侧数据与背景\n            //文字高度\n            float txtHight = getFontHeight(mTimingTxtWidth, mTimingTxtBgPaint);\n            //绘制背景\n            canvas.drawRect(mBaseWidth - mBasePaddingRight, quotes.floatY - txtHight / 2, mBaseWidth,\n                    quotes.floatY + txtHight / 2, mTimingTxtBgPaint);\n\n            //绘制实时数据\n            //距离左边的距离\n            float leftDis = 8;\n            canvas.drawText(FormatUtil.numFormat(quotes.c, mDigits),\n                    mBaseWidth - mBasePaddingRight + leftDis, quotes.floatY + txtHight / 4,\n                    mTimingTxtPaint);\n        }\n    }\n\n    private void drawTimSharingProcess(Quotes quotes, int i, Path path, Path path2) {\n        if (mViewType != KViewType.MasterViewType.TIMESHARING) return;\n\n        if (i == mBeginIndex) {\n            path.moveTo((float) (quotes.floatX - mPerX / 2.0), quotes.floatY);\n            path2.moveTo((float) (quotes.floatX - mPerX / 2.0), quotes.floatY);\n        } else if (i == mEndIndex - 1) {\n            //在这里把path圈起来，添加阴影。特别注意，这里处理下方阴影和折线边框。采用两个画笔和两个Path处理的，\n            // 貌似没有一个Paint可以同时绘制边框和填充色。\n            float bootomY = mBaseHeight - mBasePaddingBottom;\n            if (mPullType == KViewType.PullType.PULL_RIGHT_STOP) {\n                path.lineTo(quotes.floatX, quotes.floatY);\n                //开始绘制path\n                path2.lineTo(quotes.floatX, quotes.floatY);\n                path2.lineTo(quotes.floatX, bootomY);\n                path2.lineTo(mBasePaddingLeft, bootomY);\n            } else {\n                float x = (float) (quotes.floatX + mPerX / 2.0);\n                path.lineTo(x, quotes.floatY);\n                //开始绘制path\n                path2.lineTo(x, quotes.floatY);\n                path2.lineTo(x, bootomY);\n                path2.lineTo(mBasePaddingLeft, bootomY);\n            }\n            path2.close();\n        } else {\n            path.lineTo(quotes.floatX, quotes.floatY);\n            //开始绘制path\n            path2.lineTo(quotes.floatX, quotes.floatY);\n        }\n    }\n\n    /**\n     * 这里的均值如何处理：只知道最小值和最大值（mMinColseQuotes,mMaxCloseQuotes）,但是不是容器的上border和下border。\n     * 这里的处理方式是根据mMinQuotes和mMaxQuotes的差值与y轴高度的距离计算单位距离对应的值。\n     * 然后根据mMinQuotes的值(A)和底部内边距的（折线底部距离底边线的距离mInnerBottomBlankPadding）（B）\n     * 和单位对应的值(D)就可以计算出最下面border对应的值：(A-B*D)。\n     * 同理，可以计算最高对应的值。最后，均分标记即可。\n     *\n     * @param canvas\n     */\n    protected void drawYPaint(Canvas canvas) {\n        //细节处理，文字高度居中\n        float halfTxtHight;\n        double minBorderData;\n        double maxBorderData;\n        double dataDis = 0;\n\n        dataDis = mCandleMaxY - mCandleMinY;\n\n        double yDis = (mBaseHeight - mBasePaddingTop - mBasePaddingBottom - mInnerTopBlankPadding -\n                mInnerBottomBlankPadding);\n        double perY = dataDis / yDis;\n\n\n        minBorderData = mCandleMinY - mInnerBottomBlankPadding * perY;\n        maxBorderData = mCandleMaxY + mInnerTopBlankPadding * perY;\n\n        halfTxtHight = getFontHeight(mXYTxtSize, mXYTxtPaint) / 4;//应该/2的，但是不准确，原因不明\n\n        //现将最小值、最大值画好\n        float rightBorderPadding = mRightTxtPadding;\n        canvas.drawText(FormatUtil.numFormat(minBorderData, mDigits),\n                mBaseWidth - mBasePaddingRight + rightBorderPadding,\n                mBaseHeight - mBasePaddingBottom + halfTxtHight, mXYTxtPaint);\n        //draw max\n        canvas.drawText(FormatUtil.numFormat(maxBorderData, mDigits),\n                mBaseWidth - mBasePaddingRight + rightBorderPadding,\n                mBasePaddingTop + halfTxtHight, mXYTxtPaint);\n        //因为横线是均分的，所以只要取到最大值最小值的差值，均分即可。\n        float perYValues = (float) ((maxBorderData - minBorderData) / 4);\n        float perYWidth = (mBaseHeight - mBasePaddingBottom - mBasePaddingTop) / 4;\n        //从下到上依次画\n        for (int i = 1; i <= 3; i++) {\n            canvas.drawText(FormatUtil.numFormat(minBorderData + perYValues * i, mDigits),\n                    mBaseWidth - mBasePaddingRight + rightBorderPadding,\n                    mBaseHeight - mBasePaddingBottom - perYWidth * i + halfTxtHight, mXYTxtPaint);\n        }\n    }\n\n    public boolean isDrawLongPress() {\n        return mDrawLongPress;\n    }\n\n    /**\n     * 对于x轴文字的处理：其实位置已经知道，结束位置知道，x轴有效间距也知道，\n     * 计算均值即可，处理思路和y轴文字基本一致。特别注意：右边有一段间距。\n     * 这里测量直接使用最原始的时间（long类型更加方便）\n     *\n     * @param canvas\n     */\n    protected void drawXPaint(Canvas canvas) {\n        //细节，让中间虚线对应的文字居中\n        float halfTxtWidth = mXYTxtPaint.measureText(\"00:00\") / 2;\n\n        //单位间距，注意这里需要加上右边内边距\n        double perXWith = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight) / 4;\n        double xDis = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight - mInnerRightBlankPadding);\n        long timeDis = mEndQuotes.t - mBeginQuotes.t;\n        long perXTime = (long) (timeDis / xDis);\n        String showTime;\n        float finalHalfTxtWidth;\n        for (int i = 0; i < 4; i++) {\n            if (i == 0) {\n                finalHalfTxtWidth = 0;\n                //不要忘了*perXWith\n                showTime = TimeUtils.millis2String((long) (mBeginQuotes.t + perXWith * perXTime * i));\n            } else {\n                finalHalfTxtWidth = halfTxtWidth;\n                showTime = TimeUtils.millis2String((long) (mBeginQuotes.t + perXWith * perXTime * i),\n                        new SimpleDateFormat(\"HH:mm\", Locale.getDefault()));\n            }\n            canvas.drawText(showTime,\n                    (float) (mBasePaddingLeft + perXWith * i - finalHalfTxtWidth),\n                    mBaseHeight - mBasePaddingBottom + mBottomTxtPadding, mXYTxtPaint);\n        }\n    }\n\n\n    @Override\n    protected void seekAndCalculateCellData() {\n        if (mQuotesList == null || mQuotesList.isEmpty()) return;\n\n\n        //找到close最大值和最小值\n        mCandleMinY = Integer.MAX_VALUE;\n        mCandleMaxY = Integer.MIN_VALUE;\n\n\n        //对于蜡烛图，需要计算以下指标。\n        if (mViewType == KViewType.MasterViewType.CANDLE) {\n            //ma\n            FinancialAlgorithm.calculateMA(mQuotesList, 5, KViewType.MaType.ma5);\n            FinancialAlgorithm.calculateMA(mQuotesList, 10, KViewType.MaType.ma10);\n            FinancialAlgorithm.calculateMA(mQuotesList, 20, KViewType.MaType.ma20);\n            //boll\n            FinancialAlgorithm.calculateBOLL(mQuotesList);\n\n            //最终确定的最大high值和最小low值\n            mCandleMaxY = mQuotesList.get(mBeginIndex).h;\n            mCandleMinY = mQuotesList.get(mBeginIndex).l;\n        }\n\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n            if (i == mBeginIndex) {\n                mBeginQuotes = quotes;\n            }\n            if (i == mEndIndex - 1) {\n                mEndQuotes = quotes;\n            }\n\n            if (mViewType == KViewType.MasterViewType.CANDLE) {\n                if (quotes.l <= mCandleMinY) {\n                    mCandleMinY = quotes.l;\n                }\n                if (quotes.h >= mCandleMaxY) {\n                    mCandleMaxY = quotes.h;\n                }\n            } else {\n                if (quotes.c <= mCandleMinY) {\n                    mCandleMinY = quotes.c;\n                }\n                if (quotes.c >= mCandleMaxY) {\n                    mCandleMaxY = quotes.c;\n                }\n            }\n\n            //蜡烛图\n            if (mViewType == KViewType.MasterViewType.CANDLE) {\n                double max = FinancialAlgorithm.getMasterMaxY(quotes, mMasterType);\n                if (max > mCandleMaxY) {\n                    mCandleMaxY = max;\n                }\n                double min = FinancialAlgorithm.getMasterMinY(quotes, mMasterType);\n                if (min < mCandleMinY) {\n                    mCandleMinY = min;\n                }\n            }\n        }\n\n        mPerX = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight - mInnerRightBlankPadding)\n                / (mShownMaxCount);\n        double len = mCandleMaxY - mCandleMinY;\n        if (len == 0) {\n            len = Math.pow(10, -getDigits());\n        }\n        //不要忘了减去内部的上下Padding\n        mPerY = (float) ((mBaseHeight - mBasePaddingTop - mBasePaddingBottom - mInnerTopBlankPadding\n                - mInnerBottomBlankPadding) / (len));\n\n        Log.d(Constant.ESPECIAL_TAG, \"seekAndCalculateCellData,mPerY:\" + mPerY);\n\n        //重绘\n        invalidate();\n    }\n\n\n    //缩放手势监听\n    ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =\n            new ScaleGestureDetector.SimpleOnScaleGestureListener() {\n                @Override\n                public boolean onScale(ScaleGestureDetector detector) {\n                    //没有缩放\n                    if (detector.getScaleFactor() == 1) return true;\n\n                    //是放大还是缩小\n                    boolean isBigger = detector.getScaleFactor() > 1;\n\n                    //变化的个数（缩小或者放大），必须向上取整，不然当mShownMaxCount过小时容易取到0。\n                    int changeNum = (int) Math.ceil(mShownMaxCount * Math.abs(detector.getScaleFactor() - 1));\n\n                    //一半\n                    int helfChangeNum = (int) Math.ceil(changeNum / 2f);\n\n                    //缩放个数太少，直接return\n                    if (changeNum == 0 || helfChangeNum == 0) return true;\n\n                    //容错处理,获取最大最小值\n                    if (def_scale_minnum < 3) {\n                        def_scale_minnum = 3;\n                    }\n                    if (def_scale_maxnum > mQuotesList.size()) {\n                        def_scale_maxnum = mQuotesList.size();\n                    }\n\n                    //变大了(拉伸了)，数量变少了\n                    int tempCount = isBigger ? mShownMaxCount - changeNum : mShownMaxCount + changeNum;\n\n                    //缩小大到最小了或者放大到很大了\n                    if (tempCount > def_scale_maxnum || tempCount < def_scale_minnum)\n                        return true;\n\n                    mShownMaxCount = tempCount;\n\n                    //计算新的开始位置。这个地方比较难以理解:拉伸了起始点变大，并且是拉伸数量的一半，结束点变小，也是原来的一半。\n                    // 收缩，相反。可以自己画一个图看看\n                    mBeginIndex = isBigger ? mBeginIndex + helfChangeNum : mBeginIndex - helfChangeNum;\n                    if (mBeginIndex < 0) {\n                        mBeginIndex = 0;\n                    } else if ((mBeginIndex + mShownMaxCount) > mQuotesList.size()) {\n                        mBeginIndex = mQuotesList.size() - mShownMaxCount;\n                    }\n\n                    mEndIndex = mBeginIndex + mShownMaxCount;\n\n                    //将新的索引回调给副图\n                    if (mMinorListener != null)\n                        mMinorListener.masteZoomlNewIndex(mBeginIndex, mEndIndex, mShownMaxCount);\n                    if (mVolListener != null)\n                        mVolListener.masteZoomlNewIndex(mBeginIndex, mEndIndex, mShownMaxCount);\n\n                    //只要找好起始点和结束点就可以交给处理重绘的方法就好啦~\n                    seekAndCalculateCellData();\n                    return true;\n                }\n\n                @Override\n                public boolean onScaleBegin(ScaleGestureDetector detector) {\n                    //指头数量\n                    if (mFingerPressedCount != 2) return true;\n                    return true;\n                }\n            };\n\n    /**\n     * 滑动手势\n     */\n    GestureDetector.SimpleOnGestureListener mSimpleOnScaleGestureListener\n            = new GestureDetector.SimpleOnGestureListener() {\n        @Override\n        public boolean onScroll(MotionEvent e1, MotionEvent e2, final float distanceX, float distanceY) {\n            Log.d(TAG, \"onFling0: \" + distanceX + \"，\" + distanceY);\n            //降噪处理\n            if (Math.abs(distanceX) > def_onfling) {\n                //x轴幅度大于y轴\n                if (Math.abs(distanceX) > Math.abs(distanceY)) {\n                    /**\n                     * 为什么加延迟？这个取决于onFling的时机。如果不加的话，手指离开就立马结束了onFling效果。\n                     * TODO:其实这样实现效果并不是太好，是否有其他更好的解决方案？\n                     */\n                    postDelayed(() -> innerMoveViewListener(-distanceX), 200);\n                    return true;\n                }\n            }\n\n            //y轴类似\n\n            return true;\n        }\n\n        /**\n         * 这个方法是最终滑动到的位置，onScroll()才是onFling的效果回调\n         * @param e1\n         * @param e2\n         * @param distanceX\n         * @param distanceY\n         * @return\n         */\n        @Override\n        public boolean onFling(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {\n            return super.onFling(e1, e2, distanceX, distanceY);\n        }\n    };\n\n\n    /**\n     * 移动K线图计算移动的单位和重新计算起始位置和结束位置\n     *\n     * @param moveLen\n     */\n    protected void moveKView(float moveLen) {\n        //移动之前将右侧的内间距值为0\n        mInnerRightBlankPadding = 0;\n\n        mPullRight = moveLen > 0;\n        int moveCount = (int) Math.ceil(Math.abs(moveLen) / mPerX);\n        //向右拉\n        if (mPullRight) {\n            int len = mBeginIndex - moveCount;\n            if (len < def_minlen_loadmore) {\n                //加载更多\n                if (mMasterTouchListener != null && mCanLoadMore) {\n                    loadMoreIng();\n                    mMasterTouchListener.needLoadMore();\n                }\n            }\n            if (len <= 0) {\n                mBeginIndex = 0;\n                mPullType = KViewType.PullType.PULL_LEFT_STOP;\n            } else {\n                mBeginIndex = len;\n                mPullType = KViewType.PullType.PULL_LEFT;\n            }\n\n            mEndIndex = mBeginIndex + mShownMaxCount;\n            mEndIndex = mEndIndex > mQuotesList.size() ? mQuotesList.size() : mEndIndex;\n        } else {\n            int len = mEndIndex + moveCount;\n            if (len >= mQuotesList.size()) {\n                mEndIndex = mQuotesList.size();\n                mPullType = KViewType.PullType.PULL_RIGHT_STOP;\n                //重置到之前的状态\n                mInnerRightBlankPadding = DEF_INNER_RIGHT_BLANK_PADDING;\n            } else {\n                mEndIndex += moveCount;\n                mPullType = KViewType.PullType.PULL_RIGHT;\n            }\n            mBeginIndex = mEndIndex - mShownMaxCount;\n            mBeginIndex = mBeginIndex < 0 ? 0 : mBeginIndex;\n        }\n\n        //回调给副图\n        if (mMinorListener != null)\n            mMinorListener.mastelPullmNewIndex(mBeginIndex, mEndIndex, mPullType, mShownMaxCount);\n\n        if (mVolListener != null)\n            mVolListener.mastelPullmNewIndex(mBeginIndex, mEndIndex, mPullType, mShownMaxCount);\n\n        //开始位置和结束位置确认好，就可以重绘啦~\n        Log.d(TAG, \"moveKView: mBeginIndex:\" + mBeginIndex + \",mEndIndex:\" + mEndIndex);\n        seekAndCalculateCellData();\n    }\n\n    @Override\n    protected void innerClickListener() {\n        super.innerClickListener();\n        if (mViewType == KViewType.MasterViewType.CANDLE) {\n            if (mMasterType == KViewType.MasterIndicatrixType.NONE) {\n                mMasterType = KViewType.MasterIndicatrixType.MA;\n            } else if (mMasterType == KViewType.MasterIndicatrixType.MA) {\n                mMasterType = KViewType.MasterIndicatrixType.BOLL;\n            } else if (mMasterType == KViewType.MasterIndicatrixType.BOLL) {\n                mMasterType = KViewType.MasterIndicatrixType.MA_BOLL;\n            } else if (mMasterType == KViewType.MasterIndicatrixType.MA_BOLL) {\n                mMasterType = KViewType.MasterIndicatrixType.NONE;\n            }\n            //刷新界面,重绘前需要么重新计算y的边界\n            seekAndCalculateCellData();\n        }\n    }\n\n    @Override\n    protected void innerLongClickListener(float x, float y) {\n        super.innerLongClickListener(x, y);\n        mDrawLongPress = true;\n        mMovingX = x;\n        invalidate();\n    }\n\n    @Override\n    protected void innerHiddenLongClick() {\n        super.innerHiddenLongClick();\n        mDrawLongPress = false;\n        invalidate();\n        if (mMasterTouchListener != null) mMasterTouchListener.onUnLongTouch();\n        if (mMinorListener != null) mMinorListener.masterNoLongPressListener();\n        if (mVolListener != null) mVolListener.masterNoLongPressListener();\n    }\n\n    @Override\n    protected void innerMoveViewListener(float moveXLen) {\n        super.innerMoveViewListener(moveXLen);\n        moveKView(moveXLen);\n    }\n\n\n    //-----------------------对开发者暴露可以修改的参数-------\n\n    public KViewType.MasterViewType getViewType() {\n        return mViewType;\n    }\n\n    public void setViewType(KViewType.MasterViewType viewType) {\n        if (viewType == mViewType) return;\n        mViewType = viewType;\n\n        //重绘\n        seekAndCalculateCellData();\n    }\n\n\n    public Paint getBrokenLinePaint() {\n        return mBrokenLinePaint;\n    }\n\n    public MasterView setBrokenLinePaint(Paint brokenLinePaint) {\n        mBrokenLinePaint = brokenLinePaint;\n        return this;\n    }\n\n    public float getBrokenLineWidth() {\n        return mBrokenLineWidth;\n    }\n\n    public MasterView setBrokenLineWidth(float brokenLineWidth) {\n        mBrokenLineWidth = brokenLineWidth;\n        return this;\n    }\n\n    public int getBrokenLineColor() {\n        return mBrokenLineColor;\n    }\n\n    public MasterView setBrokenLineColor(int brokenLineColor) {\n        mBrokenLineColor = brokenLineColor;\n        return this;\n    }\n\n    public boolean isBrokenLineDashed() {\n        return mIsBrokenLineDashed;\n    }\n\n    public MasterView setBrokenLineDashed(boolean brokenLineDashed) {\n        mIsBrokenLineDashed = brokenLineDashed;\n        return this;\n    }\n\n    public Paint getBrokenLineBgPaint() {\n        return mBrokenLineBgPaint;\n    }\n\n    public MasterView setBrokenLineBgPaint(Paint brokenLineBgPaint) {\n        mBrokenLineBgPaint = brokenLineBgPaint;\n        return this;\n    }\n\n    public int getBrokenLineBgColor() {\n        return mBrokenLineBgColor;\n    }\n\n    public MasterView setBrokenLineBgColor(int brokenLineBgColor) {\n        mBrokenLineBgColor = brokenLineBgColor;\n        return this;\n    }\n\n    public Paint getDotPaint() {\n        return mDotPaint;\n    }\n\n    public MasterView setDotPaint(Paint dotPaint) {\n        mDotPaint = dotPaint;\n        return this;\n    }\n\n    public float getDotRadius() {\n        return mDotRadius;\n    }\n\n    public MasterView setDotRadius(float dotRadius) {\n        mDotRadius = dotRadius;\n        return this;\n    }\n\n    public int getDotColor() {\n        return mDotColor;\n    }\n\n    public MasterView setDotColor(int dotColor) {\n        mDotColor = dotColor;\n        return this;\n    }\n\n    public Paint getTimingLinePaint() {\n        return mTimingLinePaint;\n    }\n\n    public MasterView setTimingLinePaint(Paint timingLinePaint) {\n        mTimingLinePaint = timingLinePaint;\n        return this;\n    }\n\n    public float getTimingLineWidth() {\n        return mTimingLineWidth;\n    }\n\n    public MasterView setTimingLineWidth(float timingLineWidth) {\n        mTimingLineWidth = timingLineWidth;\n        return this;\n    }\n\n    public int getTimingLineColor() {\n        return mTimingLineColor;\n    }\n\n    public MasterView setTimingLineColor(int timingLineColor) {\n        mTimingLineColor = timingLineColor;\n        return this;\n    }\n\n    public boolean isTimingLineDashed() {\n        return mIsTimingLineDashed;\n    }\n\n    public MasterView setTimingLineDashed(boolean timingLineDashed) {\n        mIsTimingLineDashed = timingLineDashed;\n        return this;\n    }\n\n    public Paint getTimingTxtBgPaint() {\n        return mTimingTxtBgPaint;\n    }\n\n    public MasterView setTimingTxtBgPaint(Paint timingTxtBgPaint) {\n        mTimingTxtBgPaint = timingTxtBgPaint;\n        return this;\n    }\n\n    public Paint getTimingTxtPaint() {\n        return mTimingTxtPaint;\n    }\n\n    public MasterView setTimingTxtPaint(Paint timingTxtPaint) {\n        mTimingTxtPaint = timingTxtPaint;\n        return this;\n    }\n\n    public float getTimingTxtWidth() {\n        return mTimingTxtWidth;\n    }\n\n    public MasterView setTimingTxtWidth(float timingTxtWidth) {\n        mTimingTxtWidth = timingTxtWidth;\n        return this;\n    }\n\n    public int getTimingTxtColor() {\n        return mTimingTxtColor;\n    }\n\n    public MasterView setTimingTxtColor(int timingTxtColor) {\n        mTimingTxtColor = timingTxtColor;\n        return this;\n    }\n\n    public int getTimingTxtBgColor() {\n        return mTimingTxtBgColor;\n    }\n\n    public MasterView setTimingTxtBgColor(int timingTxtBgColor) {\n        mTimingTxtBgColor = timingTxtBgColor;\n        return this;\n    }\n\n    public Paint getLongPressTxtPaint() {\n        return mLongPressTxtPaint;\n    }\n\n    public MasterView setLongPressTxtPaint(Paint longPressTxtPaint) {\n        mLongPressTxtPaint = longPressTxtPaint;\n        return this;\n    }\n\n    public Paint getLongPressTxtBgPaint() {\n        return mLongPressTxtBgPaint;\n    }\n\n    public MasterView setLongPressTxtBgPaint(Paint longPressTxtBgPaint) {\n        mLongPressTxtBgPaint = longPressTxtBgPaint;\n        return this;\n    }\n\n    public int getLongPressTxtColor() {\n        return mLongPressTxtColor;\n    }\n\n    public MasterView setLongPressTxtColor(int longPressTxtColor) {\n        mLongPressTxtColor = longPressTxtColor;\n        return this;\n    }\n\n    public float getLongPressTxtSize() {\n        return mLongPressTxtSize;\n    }\n\n    public MasterView setLongPressTxtSize(float longPressTxtSize) {\n        mLongPressTxtSize = longPressTxtSize;\n        return this;\n    }\n\n    public int getLongPressTxtBgColor() {\n        return mLongPressTxtBgColor;\n    }\n\n    public MasterView setLongPressTxtBgColor(int longPressTxtBgColor) {\n        mLongPressTxtBgColor = longPressTxtBgColor;\n        return this;\n    }\n\n    public Paint getCandlePaint() {\n        return mCandlePaint;\n    }\n\n    public MasterView setCandlePaint(Paint candlePaint) {\n        mCandlePaint = candlePaint;\n        return this;\n    }\n\n    public int getRedCandleColor() {\n        return mRedCandleColor;\n    }\n\n    public MasterView setRedCandleColor(int redCandleColor) {\n        mRedCandleColor = redCandleColor;\n        return this;\n    }\n\n    public int getGreenCandleColor() {\n        return mGreenCandleColor;\n    }\n\n    public MasterView setGreenCandleColor(int greenCandleColor) {\n        mGreenCandleColor = greenCandleColor;\n        return this;\n    }\n\n    public int getCanldeHighLowWidth() {\n        return mCanldeHighLowWidth;\n    }\n\n    public MasterView setCanldeHighLowWidth(int canldeHighLowWidth) {\n        mCanldeHighLowWidth = canldeHighLowWidth;\n        return this;\n    }\n\n    public KViewType.MasterIndicatrixType getMasterType() {\n        return mMasterType;\n    }\n\n    public MasterView setMasterType(KViewType.MasterIndicatrixType masterType) {\n        mMasterType = masterType;\n        return this;\n    }\n\n    public Paint getMa5Paint() {\n        return mMa5Paint;\n    }\n\n    public MasterView setMa5Paint(Paint ma5Paint) {\n        mMa5Paint = ma5Paint;\n        return this;\n    }\n\n    public int getMa5Color() {\n        return mMa5Color;\n    }\n\n    public MasterView setMa5Color(int ma5Color) {\n        mMa5Color = ma5Color;\n        return this;\n    }\n\n    public Paint getMa10Paint() {\n        return mMa10Paint;\n    }\n\n    public MasterView setMa10Paint(Paint ma10Paint) {\n        mMa10Paint = ma10Paint;\n        return this;\n    }\n\n    public int getMa10Color() {\n        return mMa10Color;\n    }\n\n    public MasterView setMa10Color(int ma10Color) {\n        mMa10Color = ma10Color;\n        return this;\n    }\n\n    public Paint getMa20Paint() {\n        return mMa20Paint;\n    }\n\n    public MasterView setMa20Paint(Paint ma20Paint) {\n        mMa20Paint = ma20Paint;\n        return this;\n    }\n\n    public int getMa20Color() {\n        return mMa20Color;\n    }\n\n    public MasterView setMa20Color(int ma20Color) {\n        mMa20Color = ma20Color;\n        return this;\n    }\n\n    public Paint getBollUpPaint() {\n        return mBollUpPaint;\n    }\n\n    public MasterView setBollUpPaint(Paint bollUpPaint) {\n        mBollUpPaint = bollUpPaint;\n        return this;\n    }\n\n    public int getBollUpColor() {\n        return mBollUpColor;\n    }\n\n    public MasterView setBollUpColor(int bollUpColor) {\n        mBollUpColor = bollUpColor;\n        return this;\n    }\n\n    public Paint getBollMbPaint() {\n        return mBollMbPaint;\n    }\n\n    public MasterView setBollMbPaint(Paint bollMbPaint) {\n        mBollMbPaint = bollMbPaint;\n        return this;\n    }\n\n    public int getBollMbColor() {\n        return mBollMbColor;\n    }\n\n    public MasterView setBollMbColor(int bollMbColor) {\n        mBollMbColor = bollMbColor;\n        return this;\n    }\n\n    public Paint getBollDnPaint() {\n        return mBollDnPaint;\n    }\n\n    public MasterView setBollDnPaint(Paint bollDnPaint) {\n        mBollDnPaint = bollDnPaint;\n        return this;\n    }\n\n    public int getBollDnColor() {\n        return mBollDnColor;\n    }\n\n    public MasterView setBollDnColor(int bollDnColor) {\n        mBollDnColor = bollDnColor;\n        return this;\n    }\n\n    public double getCandleMinY() {\n        return mCandleMinY;\n    }\n\n    public MasterView setCandleMinY(double candleMinY) {\n        mCandleMinY = candleMinY;\n        return this;\n    }\n\n    public double getCandleMaxY() {\n        return mCandleMaxY;\n    }\n\n    public MasterView setCandleMaxY(double candleMaxY) {\n        mCandleMaxY = candleMaxY;\n        return this;\n    }\n\n    public float getCandleDiverWidthRatio() {\n        return mCandleDiverWidthRatio;\n    }\n\n    public MasterView setCandleDiverWidthRatio(float candleDiverWidthRatio) {\n        mCandleDiverWidthRatio = candleDiverWidthRatio;\n        return this;\n    }\n\n    public KViewListener.MinorListener getMinorListener() {\n        return mMinorListener;\n    }\n\n    public ScaleGestureDetector.OnScaleGestureListener getOnScaleGestureListener() {\n        return mOnScaleGestureListener;\n    }\n\n    public MasterView setOnScaleGestureListener(ScaleGestureDetector.OnScaleGestureListener\n                                                        onScaleGestureListener) {\n        mOnScaleGestureListener = onScaleGestureListener;\n        return this;\n    }\n\n    public int getBrokenLineBgAlpha() {\n        return mBrokenLineBgAlpha;\n    }\n\n    public MasterView setBrokenLineBgAlpha(int brokenLineBgAlpha) {\n        mBrokenLineBgAlpha = brokenLineBgAlpha;\n        return this;\n    }\n\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/MinorView.java",
    "content": "package com.tophold.trade.view.kview;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport android.graphics.Path;\nimport android.support.annotation.Nullable;\nimport android.util.AttributeSet;\nimport android.util.Log;\n\nimport com.tophold.trade.R;\nimport com.tophold.trade.utils.FormatUtil;\n\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/12/14 17:56\n * 描 述 ：副图。该view提供各种副图指标。\n * ============================================================\n **/\npublic class MinorView extends KBaseView {\n\n\n    /**\n     * 初始化所有需要的颜色资源\n     */\n    //共有的\n    int mOuterStrokeColor;\n    int mInnerXyDashColor;\n    int mXyTxtColor;\n    int mLegendTxtColor;\n    int mLongPressTxtColor;\n\n    //macd\n    int mMacdBuyColor;\n    int mMacdSellColor;\n    int mMacdDifColor;\n    int mMacdDeaColor;\n    int mMacdMacdColor;\n    Paint mMacdPaint;\n    float mMacdLineWidth = 1;\n\n\n    //rsi\n    int mRsi6Color;\n    int mRsi12Color;\n    int mRsi24Color;\n    Paint mRsiPaint;\n    float mRsiLineWidth = 1;\n\n    //kdj\n    int mKColor;\n    int mDColor;\n    int mJColor;\n    Paint mKdjPaint;\n    float mKdjLineWidth = 1;\n\n    //当前显示的指标\n    KViewType.MinorIndicatrixType mMinorType = KViewType.MinorIndicatrixType.MACD;\n\n    //y轴上最大值和最小值\n    protected double mMinY;\n    protected double mMaxY;\n    //蜡烛图间隙，大小以单个蜡烛图的宽度的比例算。可修改。\n    protected float mCandleDiverWidthRatio = 0.1f;\n\n    //监听主图的长按事件\n    private KViewListener.MinorListener mMinorListener;\n\n    public MinorView(Context context) {\n        this(context, null);\n    }\n\n    public MinorView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public MinorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initAttrs();\n        initListener();\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n        super.onLayout(changed, left, top, right, bottom);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        Log.d(TAG, \"onDraw: \" + mBaseHeight + \",\" + mBaseWidth);\n        if (mQuotesList == null || mQuotesList.isEmpty()) {\n            return;\n        }\n        //绘制右侧文字\n        drawYRightTxt(canvas);\n        //绘制图例\n        drawLegend(canvas);\n        //绘制核心指标线\n        drawMinorIndicatrix(canvas);\n        //绘制长按线\n        drawLongPress(canvas);\n    }\n\n    private void initAttrs() {\n        initDefAttrs();\n        initColorRes();\n        initMacdPaint();\n        initRsiPaint();\n        initKdjPaint();\n\n    }\n\n    private void initKdjPaint() {\n        mKdjPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mKdjPaint.setColor(mKColor);\n        mKdjPaint.setAntiAlias(true);\n        mKdjPaint.setStrokeWidth(mKdjLineWidth);\n        mKdjPaint.setStyle(Paint.Style.STROKE);\n        mKdjPaint.setTextSize(mLegendTxtSize);\n    }\n\n    private void initRsiPaint() {\n        mRsiPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mRsiPaint.setColor(mRsi6Color);\n        mRsiPaint.setAntiAlias(true);\n        mRsiPaint.setStrokeWidth(mRsiLineWidth);\n        mRsiPaint.setStyle(Paint.Style.STROKE);\n        mRsiPaint.setTextSize(mLegendTxtSize);\n    }\n\n    private void initMacdPaint() {\n        mMacdPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mMacdPaint.setColor(mMacdBuyColor);\n        mMacdPaint.setAntiAlias(true);\n        mMacdPaint.setStrokeWidth(mMacdLineWidth);\n        mMacdPaint.setTextSize(mLegendTxtSize);\n    }\n\n    private void initDefAttrs() {\n        //重写内边距大小\n        mInnerTopBlankPadding = 8;\n        mInnerBottomBlankPadding = 8;\n\n        //重写Legend padding\n        mLegendPaddingTop = 0;\n        mLegendPaddingRight = 4;\n        mLegendPaddingLeft = 4;\n\n\n        setShowInnerX(false);\n        setShowInnerY(true);\n    }\n\n    private void initColorRes() {\n        //颜色\n        mOuterStrokeColor = getColor(R.color.color_minorView_outerStrokeColor);\n        mInnerXyDashColor = getColor(R.color.color_minorView_innerXyDashColor);\n        mXyTxtColor = getColor(R.color.color_minorView_xYTxtColor);\n        mLegendTxtColor = getColor(R.color.color_minorView_legendTxtColor);\n        mLongPressTxtColor = getColor(R.color.color_minorView_longPressTxtColor);\n        mMacdBuyColor = getColor(R.color.color_minorView_macdBuyColor);\n        mMacdSellColor = getColor(R.color.color_minorView_macdSellColor);\n        mMacdDifColor = getColor(R.color.color_minorView_macdDifColor);\n        mMacdDeaColor = getColor(R.color.color_minorView_macdDeaColor);\n        mMacdMacdColor = getColor(R.color.color_minorView_macdMacdColor);\n        mRsi6Color = getColor(R.color.color_minorView_rsi6Color);\n        mRsi12Color = getColor(R.color.color_minorView_rsi12Color);\n        mRsi24Color = getColor(R.color.color_minorView_rsi24Color);\n        mKColor = getColor(R.color.color_minorView_kColor);\n        mDColor = getColor(R.color.color_minorView_dColor);\n        mJColor = getColor(R.color.color_minorView_jColor);\n    }\n\n    private void initListener() {\n        mMinorListener = new KViewListener.MinorListener() {\n            @Override\n            public void masterLongPressListener(int pressIndex, Quotes currQuotes) {\n                mDrawLongPress = true;\n                mCurrLongPressQuotes = mQuotesList.get(pressIndex);\n                invalidate();\n            }\n\n            @Override\n            public void masterNoLongPressListener() {\n                mDrawLongPress = false;\n                invalidate();\n            }\n\n            @Override\n            public void masteZoomlNewIndex(int beginIndex, int endIndex, int shownMaxCount) {\n                mBeginIndex = beginIndex;\n                mEndIndex = endIndex;\n                mShownMaxCount = shownMaxCount;\n                seekAndCalculateCellData();\n            }\n\n            @Override\n            public void mastelPullmNewIndex(int beginIndex, int endIndex, KViewType.PullType currPullType, int shownMaxCount) {\n                mBeginIndex = beginIndex;\n                mEndIndex = endIndex;\n                mShownMaxCount = shownMaxCount;\n                mPullType = currPullType;\n\n                //处理右侧内边距\n                if (currPullType == KViewType.PullType.PULL_RIGHT_STOP) {\n                    //重置到之前的状态\n                    mInnerRightBlankPadding = DEF_INNER_RIGHT_BLANK_PADDING;\n                } else {\n                    mInnerRightBlankPadding = 0;\n                }\n\n                seekAndCalculateCellData();\n            }\n        };\n    }\n\n    private void drawLegend(Canvas canvas) {\n        //绘制非按下情况下图例\n        drawNoPressLegend(canvas);\n        //绘制按下的图例\n        drawPressLegend(canvas);\n    }\n\n    private void drawMinorIndicatrix(Canvas canvas) {\n        mMacdPaint.setStyle(Paint.Style.STROKE);\n        mRsiPaint.setStyle(Paint.Style.STROKE);\n        mKdjPaint.setStyle(Paint.Style.STROKE);\n        if (mMinorType == KViewType.MinorIndicatrixType.MACD) {\n            drawMACD(canvas);\n        } else if (mMinorType == KViewType.MinorIndicatrixType.RSI) {\n            drawRSI(canvas);\n        } else if (mMinorType == KViewType.MinorIndicatrixType.KDJ) {\n            drawKDJ(canvas);\n        }\n    }\n\n    private void drawLongPress(Canvas canvas) {\n        if (!mDrawLongPress) return;\n        if (mCurrLongPressQuotes == null) return;\n\n        //y轴线\n        canvas.drawLine(mCurrLongPressQuotes.floatX, mBasePaddingTop, mCurrLongPressQuotes.floatX,\n                mBaseHeight - mBasePaddingBottom, mLongPressPaint);\n    }\n\n    private void drawPressLegend(Canvas canvas) {\n        if (!mDrawLongPress) return;\n\n        mMacdPaint.setStyle(Paint.Style.FILL);\n        mRsiPaint.setStyle(Paint.Style.FILL);\n        mKdjPaint.setStyle(Paint.Style.FILL);\n\n        float x = (float) (mLegendPaddingLeft + mBasePaddingLeft);\n        float y = (float) (mLegendPaddingTop + mBasePaddingTop) + getFontHeight(mLegendTxtSize, mMacdPaint);\n\n        String showTxt;\n        switch (mMinorType) {\n            case MACD:\n                showTxt = \"DIFF:\" + FormatUtil.numFormat(mCurrLongPressQuotes.dif, mDigits) + \" \";\n                mMacdPaint.setColor(mMacdDifColor);\n                canvas.drawText(showTxt, x,\n                        y, mMacdPaint);\n\n                float leftWidth11 = mMacdPaint.measureText(showTxt);\n                showTxt = \"DEA:\" + FormatUtil.numFormat(mCurrLongPressQuotes.dea, mDigits) + \" \";\n                mMacdPaint.setColor(mMacdDeaColor);\n                canvas.drawText(showTxt, x + leftWidth11, y, mMacdPaint);\n\n                float leftWidth12 = mMacdPaint.measureText(showTxt);\n                showTxt = \"MACD:\" + FormatUtil.numFormat(mCurrLongPressQuotes.macd, mDigits) + \" \";\n                mMacdPaint.setColor(mMacdMacdColor);\n                canvas.drawText(showTxt, (x + leftWidth11 + leftWidth12),\n                        y, mMacdPaint);\n                break;\n            case RSI:\n                showTxt = \"RSI6:\" + FormatUtil.numFormat(mCurrLongPressQuotes.rsi6, mDigits) + \" \";\n                mRsiPaint.setColor(mRsi6Color);\n                canvas.drawText(showTxt, (x),\n                        y, mRsiPaint);\n\n                float leftWidth21 = mRsiPaint.measureText(showTxt);\n                showTxt = \"RSI12:\" + FormatUtil.numFormat(mCurrLongPressQuotes.rsi12, mDigits) + \" \";\n                mRsiPaint.setColor(mRsi12Color);\n                canvas.drawText(showTxt, (x + leftWidth21),\n                        y, mRsiPaint);\n\n                float leftWidth22 = mRsiPaint.measureText(showTxt);\n                showTxt = \"RSI24:\" + FormatUtil.numFormat(mCurrLongPressQuotes.rsi24, mDigits) + \" \";\n                mRsiPaint.setColor(mRsi24Color);\n                canvas.drawText(showTxt, (x + leftWidth21 + leftWidth22),\n                        y, mRsiPaint);\n                break;\n            case KDJ:\n                showTxt = \"K:\" + FormatUtil.numFormat(mCurrLongPressQuotes.k, mDigits) + \" \";\n                mKdjPaint.setColor(mKColor);\n                canvas.drawText(showTxt, (x),\n                        y, mKdjPaint);\n\n                float leftWidth = mKdjPaint.measureText(showTxt);\n                showTxt = \"D:\" + FormatUtil.numFormat(mCurrLongPressQuotes.d, mDigits) + \" \";\n                mKdjPaint.setColor(mDColor);\n                canvas.drawText(showTxt, (x + leftWidth),\n                        y, mKdjPaint);\n\n                float leftWidth2 = mKdjPaint.measureText(showTxt);\n                showTxt = \"J:\" + FormatUtil.numFormat(mCurrLongPressQuotes.j, mDigits) + \" \";\n                mKdjPaint.setColor(mJColor);\n                canvas.drawText(showTxt, (x + leftWidth + leftWidth2),\n                        y, mKdjPaint);\n                break;\n            default:\n                break;\n        }\n\n    }\n\n    private void drawNoPressLegend(Canvas canvas) {\n        if (mDrawLongPress) return;\n        String showTxt = \"\";\n        if (mMinorType == KViewType.MinorIndicatrixType.MACD) {\n            showTxt = \"MACD(12,26,9)\";\n        } else if (mMinorType == KViewType.MinorIndicatrixType.RSI) {\n            showTxt = \"RSI(6,12,24)\";\n        } else if (mMinorType == KViewType.MinorIndicatrixType.KDJ) {\n            showTxt = \"KDJ(9,3,3)\";\n        }\n        canvas.drawText(showTxt,\n                (float) (mBaseWidth - mLegendPaddingRight - mBasePaddingRight - mLegendPaint.measureText(showTxt)),\n                (float) (mLegendPaddingTop + mBasePaddingTop + getFontHeight(mLegendTxtSize, mLegendPaint)), mLegendPaint);\n    }\n\n    private void drawYRightTxt(Canvas canvas) {\n        //绘制右侧的y轴文字\n        //现将最小值、最大值画好\n        float halfTxtHight = getFontHeight(mXYTxtSize, mXYTxtPaint) / 2;//应该/2的，但是不准确，原因不明\n        float x = mBaseWidth - mBasePaddingRight + mRightTxtPadding;\n        float maxY = mBasePaddingTop + halfTxtHight + mInnerTopBlankPadding;\n        float minY = mBaseHeight - mBasePaddingBottom - halfTxtHight - mInnerBottomBlankPadding;\n        //draw min\n        canvas.drawText(FormatUtil.numFormat(mMinY, mDigits),\n                x,\n                minY, mXYTxtPaint);\n        //draw max\n        canvas.drawText(FormatUtil.numFormat(mMaxY, mDigits),\n                x,\n                maxY, mXYTxtPaint);\n        //draw middle\n        canvas.drawText(FormatUtil.numFormat((mMaxY + mMinY) / 2.0, mDigits),\n                x, (minY + maxY) / 2.0f,\n                mXYTxtPaint);\n    }\n\n    private void drawMACD(Canvas canvas) {\n\n        //macd\n        //首先寻找\"0\"点，这个点是正负macd的分界点\n        float v = mBaseHeight - mBasePaddingBottom - mInnerBottomBlankPadding;\n        double zeroY = v - mPerY * (0 - mMinY);\n        float startX, startY, stopX, stopY;\n\n        //dif\n        float difX, difY;\n        Path difPath = new Path();\n\n        //dea\n        float deaX, deaY;\n        Path deaPath = new Path();\n\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n\n            /*macd*/\n            //找另外一个y点\n            double y = v - mPerY * (quotes.macd - mMinY);\n            startX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mCandleDiverWidthRatio * mPerX / 2;\n            stopX = mBasePaddingLeft + (i - mBeginIndex + 1) * mPerX - mCandleDiverWidthRatio * mPerX / 2;\n            startY = (float) zeroY;\n            stopY = (float) y;\n            if (quotes.macd > 0) {\n                mMacdPaint.setColor(mMacdBuyColor);\n            } else {\n                mMacdPaint.setColor(mMacdSellColor);\n            }\n            //            Log.e(TAG, \"drawMACD: \"+startY+\",\"+stopY +\n            //                    \",\"+(mBasePaddingTop+mInnerTopBlankPadding)+\",\"+\n            //                    (mBaseHeight-mBasePaddingBottom-mInnerBottomBlankPadding));\n            mMacdPaint.setStyle(Paint.Style.FILL);\n            canvas.drawRect(startX, startY, stopX, stopY, mMacdPaint);\n\n\n            /*dif*/\n            difX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            difY = (float) (v - mPerY * (quotes.dif - mMinY));\n            if (i == mBeginIndex) {\n                difPath.moveTo(difX - mPerX / 2, difY);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    difX += mPerX / 2;//最后一个点特殊处理\n                }\n                difPath.lineTo(difX, difY);\n            }\n            mMacdPaint.setStyle(Paint.Style.STROKE);\n            mMacdPaint.setColor(mMacdDifColor);\n            canvas.drawPath(difPath, mMacdPaint);\n\n\n            /*dea*/\n            deaX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            deaY = (float) (v - mPerY * (quotes.dea - mMinY));\n            if (i == mBeginIndex) {\n                deaPath.moveTo(deaX - mPerX / 2, deaY);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    deaX += mPerX / 2;//最后一个点特殊处理\n                }\n                deaPath.lineTo(deaX, deaY);\n            }\n            mMacdPaint.setStyle(Paint.Style.STROKE);\n            mMacdPaint.setColor(mMacdDeaColor);\n            canvas.drawPath(deaPath, mMacdPaint);\n        }\n\n    }\n\n    private void drawRSI(Canvas canvas) {\n\n        float rsiX;\n\n        //rsi6\n        float rsi6Y;\n        Path rsi6Path = new Path();\n\n        //rsi12\n        float rsi12Y;\n        Path rsi12Path = new Path();\n\n        //rsi24\n        float rsi24Y;\n        Path rsi24Path = new Path();\n\n        float v = mBaseHeight - mBasePaddingBottom - mInnerBottomBlankPadding;\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n\n            /*rsi6*/\n            rsiX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            rsi6Y = (float) (v - mPerY * (quotes.rsi6 - mMinY));\n            if (i == mBeginIndex) {\n                rsi6Path.moveTo(rsiX - mPerX / 2, rsi6Y);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    rsiX += mPerX / 2;//最后一个点特殊处理\n                }\n                rsi6Path.lineTo(rsiX, rsi6Y);\n            }\n            mRsiPaint.setColor(mRsi6Color);\n            canvas.drawPath(rsi6Path, mRsiPaint);\n\n            /*rsi12*/\n            //为什么这里重复再赋一遍值？因为下面有一个\"rsiX +=\"操作\n            rsiX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            rsi12Y = (float) (v - mPerY * (quotes.rsi12 - mMinY));\n            if (i == mBeginIndex) {\n                rsi12Path.moveTo(rsiX - mPerX / 2, rsi12Y);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    rsiX += mPerX / 2;//最后一个点特殊处理\n                }\n                rsi12Path.lineTo(rsiX, rsi12Y);\n            }\n            mRsiPaint.setColor(mRsi12Color);\n            canvas.drawPath(rsi12Path, mRsiPaint);\n\n             /*rsi24*/\n            //为什么这里重复再赋一遍值？因为下面有一个\"rsiX +=\"操作\n            rsiX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            rsi24Y = (float) (v - mPerY * (quotes.rsi24 - mMinY));\n            if (i == mBeginIndex) {\n                rsi24Path.moveTo(rsiX - mPerX / 2, rsi24Y);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    rsiX += mPerX / 2;//最后一个点特殊处理\n                }\n                rsi24Path.lineTo(rsiX, rsi24Y);\n            }\n            mRsiPaint.setColor(mRsi24Color);\n            canvas.drawPath(rsi24Path, mRsiPaint);\n\n        }\n    }\n\n    private void drawKDJ(Canvas canvas) {\n\n        float kdjX;\n\n        //k\n        float kY;\n        Path kPath = new Path();\n\n        //d\n        float dY;\n        Path dPath = new Path();\n\n        //j\n        float jY;\n        Path jPath = new Path();\n\n        float v = mBaseHeight - mBasePaddingBottom - mInnerBottomBlankPadding;\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n\n            /*k*/\n            kdjX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            kY = (float) (v - mPerY * (quotes.k - mMinY));\n            if (i == mBeginIndex) {\n                kPath.moveTo(kdjX - mPerX / 2, kY);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    kdjX += mPerX / 2;//最后一个点特殊处理\n                }\n                kPath.lineTo(kdjX, kY);\n            }\n            mKdjPaint.setColor(mKColor);\n            canvas.drawPath(kPath, mKdjPaint);\n\n            /*d*/\n            kdjX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            dY = (float) (v - mPerY * (quotes.d - mMinY));\n            if (i == mBeginIndex) {\n                dPath.moveTo(kdjX - mPerX / 2, dY);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    kdjX += mPerX / 2;//最后一个点特殊处理\n                }\n                dPath.lineTo(kdjX, dY);\n            }\n            mKdjPaint.setColor(mDColor);\n            canvas.drawPath(dPath, mKdjPaint);\n\n             /*j*/\n            kdjX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            jY = (float) (v - mPerY * (quotes.j - mMinY));\n            if (i == mBeginIndex) {\n                jPath.moveTo(kdjX - mPerX / 2, jY);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    kdjX += mPerX / 2;//最后一个点特殊处理\n                }\n                jPath.lineTo(kdjX, jY);\n            }\n            mKdjPaint.setColor(mJColor);\n            canvas.drawPath(jPath, mKdjPaint);\n\n        }\n    }\n\n    @Override\n    protected void seekAndCalculateCellData() {\n        if (mQuotesList == null || mQuotesList.isEmpty()) return;\n\n        if (mMinorType == KViewType.MinorIndicatrixType.MACD) {\n            FinancialAlgorithm.calculateMACD(mQuotesList);\n        } else if (mMinorType == KViewType.MinorIndicatrixType.RSI) {\n            FinancialAlgorithm.calculateRSI(mQuotesList);\n        } else if (mMinorType == KViewType.MinorIndicatrixType.KDJ) {\n            FinancialAlgorithm.calculateKDJ(mQuotesList);\n        }\n\n        //找到close最大值和最小值\n        mMinY = Integer.MAX_VALUE;\n        mMaxY = Integer.MIN_VALUE;\n\n\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n            if (i == mBeginIndex) {\n                mBeginQuotes = quotes;\n            }\n            if (i == mEndIndex - 1) {\n                mEndQuotes = quotes;\n            }\n            double min = FinancialAlgorithm.getMinorMinY(quotes, mMinorType);\n            double max = FinancialAlgorithm.getMinorMaxY(quotes, mMinorType);\n\n            if (min <= mMinY) {\n                mMinY = min;\n            }\n            if (max >= mMaxY) {\n                mMaxY = max;\n            }\n\n        }\n\n\n        mPerX = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight - mInnerRightBlankPadding)\n                / (mShownMaxCount);\n        //不要忘了减去内部的上下Padding\n        mPerY = (float) ((mBaseHeight - mBasePaddingTop - mBasePaddingBottom - mInnerTopBlankPadding\n                - mInnerBottomBlankPadding) / (mMaxY - mMinY));\n        Log.e(TAG, \"seekAndCalculateCellData: mMinY：\" + mMinY + \",mMaxY:\" + mMaxY);\n        //重绘\n        invalidate();\n    }\n\n    @Override\n    protected void innerClickListener() {\n        super.innerClickListener();\n        if (mMinorType == KViewType.MinorIndicatrixType.MACD) {\n            mMinorType = KViewType.MinorIndicatrixType.RSI;\n        } else if (mMinorType == KViewType.MinorIndicatrixType.RSI) {\n            mMinorType = KViewType.MinorIndicatrixType.KDJ;\n        } else if (mMinorType == KViewType.MinorIndicatrixType.KDJ) {\n            mMinorType = KViewType.MinorIndicatrixType.MACD;\n        }\n        setMinorType(mMinorType);\n    }\n\n    @Override\n    protected void innerLongClickListener(float x, float y) {\n        super.innerLongClickListener(x, y);\n\n    }\n\n    @Override\n    protected void innerHiddenLongClick() {\n        super.innerHiddenLongClick();\n    }\n\n    @Override\n    protected void innerMoveViewListener(float moveXLen) {\n        super.innerMoveViewListener(moveXLen);\n\n    }\n\n\n    //-----------------------对开发者暴露可以修改的参数-------\n\n    public void setMinorType(KViewType.MinorIndicatrixType minorType) {\n        mMinorType = minorType;\n\n        seekAndCalculateCellData();\n    }\n\n    public int getOuterStrokeColor() {\n        return mOuterStrokeColor;\n    }\n\n    public MinorView setOuterStrokeColor(int outerStrokeColor) {\n        mOuterStrokeColor = outerStrokeColor;\n        return this;\n    }\n\n    public int getInnerXyDashColor() {\n        return mInnerXyDashColor;\n    }\n\n    public MinorView setInnerXyDashColor(int innerXyDashColor) {\n        mInnerXyDashColor = innerXyDashColor;\n        return this;\n    }\n\n    public int getXyTxtColor() {\n        return mXyTxtColor;\n    }\n\n    public MinorView setXyTxtColor(int xyTxtColor) {\n        mXyTxtColor = xyTxtColor;\n        return this;\n    }\n\n    public int getLegendTxtColor() {\n        return mLegendTxtColor;\n    }\n\n    public MinorView setLegendTxtColor(int legendTxtColor) {\n        mLegendTxtColor = legendTxtColor;\n        return this;\n    }\n\n    public int getLongPressTxtColor() {\n        return mLongPressTxtColor;\n    }\n\n    public MinorView setLongPressTxtColor(int longPressTxtColor) {\n        mLongPressTxtColor = longPressTxtColor;\n        return this;\n    }\n\n    public int getMacdBuyColor() {\n        return mMacdBuyColor;\n    }\n\n    public MinorView setMacdBuyColor(int macdBuyColor) {\n        mMacdBuyColor = macdBuyColor;\n        return this;\n    }\n\n    public int getMacdSellColor() {\n        return mMacdSellColor;\n    }\n\n    public MinorView setMacdSellColor(int macdSellColor) {\n        mMacdSellColor = macdSellColor;\n        return this;\n    }\n\n    public int getMacdDifColor() {\n        return mMacdDifColor;\n    }\n\n    public MinorView setMacdDifColor(int macdDifColor) {\n        mMacdDifColor = macdDifColor;\n        return this;\n    }\n\n    public int getMacdDeaColor() {\n        return mMacdDeaColor;\n    }\n\n    public MinorView setMacdDeaColor(int macdDeaColor) {\n        mMacdDeaColor = macdDeaColor;\n        return this;\n    }\n\n    public int getMacdMacdColor() {\n        return mMacdMacdColor;\n    }\n\n    public MinorView setMacdMacdColor(int macdMacdColor) {\n        mMacdMacdColor = macdMacdColor;\n        return this;\n    }\n\n    public Paint getMacdPaint() {\n        return mMacdPaint;\n    }\n\n    public MinorView setMacdPaint(Paint macdPaint) {\n        mMacdPaint = macdPaint;\n        return this;\n    }\n\n    public float getMacdLineWidth() {\n        return mMacdLineWidth;\n    }\n\n    public MinorView setMacdLineWidth(float macdLineWidth) {\n        mMacdLineWidth = macdLineWidth;\n        return this;\n    }\n\n    public int getRsi6Color() {\n        return mRsi6Color;\n    }\n\n    public MinorView setRsi6Color(int rsi6Color) {\n        mRsi6Color = rsi6Color;\n        return this;\n    }\n\n    public int getRsi12Color() {\n        return mRsi12Color;\n    }\n\n    public MinorView setRsi12Color(int rsi12Color) {\n        mRsi12Color = rsi12Color;\n        return this;\n    }\n\n    public int getRsi24Color() {\n        return mRsi24Color;\n    }\n\n    public MinorView setRsi24Color(int rsi24Color) {\n        mRsi24Color = rsi24Color;\n        return this;\n    }\n\n    public Paint getRsiPaint() {\n        return mRsiPaint;\n    }\n\n    public MinorView setRsiPaint(Paint rsiPaint) {\n        mRsiPaint = rsiPaint;\n        return this;\n    }\n\n    public float getRsiLineWidth() {\n        return mRsiLineWidth;\n    }\n\n    public MinorView setRsiLineWidth(float rsiLineWidth) {\n        mRsiLineWidth = rsiLineWidth;\n        return this;\n    }\n\n    public int getKColor() {\n        return mKColor;\n    }\n\n    public MinorView setKColor(int KColor) {\n        mKColor = KColor;\n        return this;\n    }\n\n    public int getDColor() {\n        return mDColor;\n    }\n\n    public MinorView setDColor(int DColor) {\n        mDColor = DColor;\n        return this;\n    }\n\n    public int getJColor() {\n        return mJColor;\n    }\n\n    public MinorView setJColor(int JColor) {\n        mJColor = JColor;\n        return this;\n    }\n\n    public Paint getKdjPaint() {\n        return mKdjPaint;\n    }\n\n    public MinorView setKdjPaint(Paint kdjPaint) {\n        mKdjPaint = kdjPaint;\n        return this;\n    }\n\n    public float getKdjLineWidth() {\n        return mKdjLineWidth;\n    }\n\n    public MinorView setKdjLineWidth(float kdjLineWidth) {\n        mKdjLineWidth = kdjLineWidth;\n        return this;\n    }\n\n    public KViewType.MinorIndicatrixType getMinorType() {\n        return mMinorType;\n    }\n\n    public double getMinY() {\n        return mMinY;\n    }\n\n    public MinorView setMinY(double minY) {\n        mMinY = minY;\n        return this;\n    }\n\n    public double getMaxY() {\n        return mMaxY;\n    }\n\n    public MinorView setMaxY(double maxY) {\n        mMaxY = maxY;\n        return this;\n    }\n\n    public float getCandleDiverWidthRatio() {\n        return mCandleDiverWidthRatio;\n    }\n\n    public MinorView setCandleDiverWidthRatio(float candleDiverWidthRatio) {\n        mCandleDiverWidthRatio = candleDiverWidthRatio;\n        return this;\n    }\n\n    public MinorView setMinorListener(KViewListener.MinorListener minorListener) {\n        mMinorListener = minorListener;\n        return this;\n    }\n\n    public KViewListener.MinorListener getMinorListener() {\n        return mMinorListener;\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/Quotes.java",
    "content": "package com.tophold.trade.view.kview;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\nimport com.tophold.trade.utils.TimeUtils;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/11/21 11:12\n * 描 述 ：包装后的Quotes，实际使用的Quotes\n * ============================================================\n **/\npublic class Quotes implements Serializable {\n\n    /**\n     * 原始数据\n     */\n    public long t;//开始时间\n    public double o;\n    public double h;\n    public double l;\n    public double c;\n\n    //扩展一个结束时间\n    public long e;\n\n    //vol 量，可选\n    public double vol;\n\n    /**\n     * 适配数据的构造方法，包括五个参数，全部必须。价格格式为String类型\n     *\n     * @param o 闭盘价\n     * @param h 最高价\n     * @param l 最低价\n     * @param c 收盘价\n     * @param t 时间\n     */\n    public Quotes(String o, String h, String l, String c, String t) {\n        this(Double.parseDouble(o), Double.parseDouble(h), Double.parseDouble(l), Double.parseDouble(c), TimeUtils.date2Millis(new Date(t)));\n    }\n\n    /**\n     * 价格格式是double类型\n     *\n     * @param o\n     * @param h\n     * @param l\n     * @param c\n     * @param t\n     */\n    public Quotes(double o, double h, double l, double c, long t) {\n        this(o, h, l, c, t, -1, -1);\n    }\n\n    public Quotes(double o, double h, double l, double c, long t, double vol) {\n        this(o, h, l, c, t, -1, vol);\n    }\n\n    /**\n     * 最原始构造方法\n     *\n     * @param o\n     * @param h\n     * @param l\n     * @param c\n     * @param t\n     * @param e\n     */\n    public Quotes(double o, double h, double l, double c, long t, long e, double vol) {\n        this.o = o;\n        this.h = h;\n        this.l = l;\n        this.c = c;\n        this.t = t;\n        this.e = e;\n        this.vol = vol;\n    }\n\n    /**\n     * 多添加一个时间，包括两个格式的时间，一个开始时间，一个结束时间，标准以开始时间为准。\n     *\n     * @param o\n     * @param h\n     * @param l\n     * @param c\n     * @param s\n     * @param e\n     */\n    public Quotes(String o, String h, String l, String c, long s, long e) {\n        this(Double.parseDouble(o), Double.parseDouble(h), Double.parseDouble(l), Double.parseDouble(c), s, e, -1);\n\n    }\n\n    /**\n     * 扩展的数据\n     */\n    //实际中展示的时间\n    private String showTime;\n\n    public String getShowTime() {\n        showTime = TimeUtils.millis2String(t);\n        return showTime;\n    }\n\n    //在自定义view:FundView中的位置坐标\n    public float floatX;\n    public float floatY;\n\n    //MA\n    public double ma5;\n    public double ma10;\n    public double ma20;\n\n    //BOLL\n    public double up;//上轨线\n    public double mb;//中轨线\n    public double dn;//下轨线\n\n    //KDJ\n    public double k;\n    public double d;\n    public double j;\n\n    //macd\n    public double dif;\n    public double dea;\n    public double macd;\n\n    //rsi\n    public double rsi6;\n    public double rsi12;\n    public double rsi24;\n\n    //vol\n    public double volMa5;\n    public double volMa10;\n\n    @Override\n    public String toString() {\n        return \"Quotes{\" +\n                \"t=\" + t +\n                \", o=\" + o +\n                \", h=\" + h +\n                \", l=\" + l +\n                \", c=\" + c +\n                \", e=\" + e +\n                \", vol=\" + vol +\n                \", showTime='\" + showTime + '\\'' +\n                \", floatX=\" + floatX +\n                \", floatY=\" + floatY +\n                \", ma5=\" + ma5 +\n                \", ma10=\" + ma10 +\n                \", ma20=\" + ma20 +\n                \", up=\" + up +\n                \", mb=\" + mb +\n                \", dn=\" + dn +\n                \", k=\" + k +\n                \", d=\" + d +\n                \", j=\" + j +\n                \", dif=\" + dif +\n                \", dea=\" + dea +\n                \", macd=\" + macd +\n                \", rsi6=\" + rsi6 +\n                \", rsi12=\" + rsi12 +\n                \", rsi24=\" + rsi24 +\n                \", volMa5=\" + volMa5 +\n                \", volMa10=\" + volMa10 +\n                '}';\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/VolModel.java",
    "content": "package com.tophold.trade.view.kview;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/07/08 21:24\n * 描 述 ：量\n * ============================================================\n */\npublic class VolModel {\n    public boolean cUp;//当前收盘价是否大于等于前一天收盘价\n    public double vol;//量\n    public double ma5;\n    public double ma10;\n\n    public VolModel(boolean cUp, double vol, double ma5, double ma10) {\n        this.cUp = cUp;\n        this.vol = vol;\n        this.ma5 = ma5;\n        this.ma10 = ma10;\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/kview/VolView.java",
    "content": "package com.tophold.trade.view.kview;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport android.graphics.Path;\nimport android.support.annotation.Nullable;\nimport android.util.AttributeSet;\nimport android.util.Log;\n\nimport com.tophold.trade.R;\nimport com.tophold.trade.utils.FormatUtil;\n\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 创建日期 ：2017/12/14 17:56\n * 描 述 ：量图，从本质上来说基本和副图一致。\n * ============================================================\n **/\npublic class VolView extends KBaseView {\n\n\n    /**\n     * 初始化所有需要的颜色资源\n     */\n    //共有的\n    int mOuterStrokeColor;\n    int mInnerXyDashColor;\n    int mXyTxtColor;\n    int mLegendTxtColor;\n    int mLongPressTxtColor;\n\n    //macd\n    int mMacdBuyColor;\n    int mMacdSellColor;\n    int mMacdDifColor;\n    int mMacdDeaColor;\n    int mMacdMacdColor;\n    Paint mMacdPaint;\n    float mMacdLineWidth = 1;\n\n\n    //rsi\n    int mRsi6Color;\n    int mRsi12Color;\n    int mRsi24Color;\n    Paint mRsiPaint;\n    float mRsiLineWidth = 1;\n\n    //kdj\n    int mKColor;\n    int mDColor;\n    int mJColor;\n    Paint mKdjPaint;\n    float mKdjLineWidth = 1;\n\n    //当前显示的指标\n    KViewType.MinorIndicatrixType mMinorType = KViewType.MinorIndicatrixType.MACD;\n\n    //y轴上最大值和最小值\n    protected double mMinY;\n    protected double mMaxY;\n    //蜡烛图间隙，大小以单个蜡烛图的宽度的比例算。可修改。\n    protected float mCandleDiverWidthRatio = 0.1f;\n\n    //监听主图的长按事件\n    private KViewListener.MinorListener mVolListener;\n\n    //是否展示量图\n    private boolean mShowVol = false;\n\n    public VolView(Context context) {\n        this(context, null);\n    }\n\n    public VolView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public VolView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initAttrs();\n        initListener();\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n    }\n\n    @Override\n    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n        super.onLayout(changed, left, top, right, bottom);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        Log.d(TAG, \"onDraw: \" + mBaseHeight + \",\" + mBaseWidth);\n        if (mQuotesList == null || mQuotesList.isEmpty()) {\n            return;\n        }\n        //绘制右侧文字\n        drawYRightTxt(canvas);\n        //绘制图例\n        drawLegend(canvas);\n        //绘制核心指标线\n        drawMinorIndicatrix(canvas);\n        //绘制长按线\n        drawLongPress(canvas);\n    }\n\n    private void initAttrs() {\n        initDefAttrs();\n        initColorRes();\n        initMacdPaint();\n        initRsiPaint();\n        initKdjPaint();\n\n    }\n\n    private void initKdjPaint() {\n        mKdjPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mKdjPaint.setColor(mKColor);\n        mKdjPaint.setAntiAlias(true);\n        mKdjPaint.setStrokeWidth(mKdjLineWidth);\n        mKdjPaint.setStyle(Paint.Style.STROKE);\n        mKdjPaint.setTextSize(mLegendTxtSize);\n    }\n\n    private void initRsiPaint() {\n        mRsiPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mRsiPaint.setColor(mRsi6Color);\n        mRsiPaint.setAntiAlias(true);\n        mRsiPaint.setStrokeWidth(mRsiLineWidth);\n        mRsiPaint.setStyle(Paint.Style.STROKE);\n        mRsiPaint.setTextSize(mLegendTxtSize);\n    }\n\n    private void initMacdPaint() {\n        mMacdPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mMacdPaint.setColor(mMacdBuyColor);\n        mMacdPaint.setAntiAlias(true);\n        mMacdPaint.setStrokeWidth(mMacdLineWidth);\n        mMacdPaint.setTextSize(mLegendTxtSize);\n    }\n\n    private void initDefAttrs() {\n        //重写内边距大小\n        mInnerTopBlankPadding = 8;\n        mInnerBottomBlankPadding = 8;\n\n        //重写Legend padding\n        mLegendPaddingTop = 0;\n        mLegendPaddingRight = 4;\n        mLegendPaddingLeft = 4;\n\n\n        setShowInnerX(false);\n        setShowInnerY(true);\n    }\n\n    private void initColorRes() {\n        //颜色\n        mOuterStrokeColor = getColor(R.color.color_minorView_outerStrokeColor);\n        mInnerXyDashColor = getColor(R.color.color_minorView_innerXyDashColor);\n        mXyTxtColor = getColor(R.color.color_minorView_xYTxtColor);\n        mLegendTxtColor = getColor(R.color.color_minorView_legendTxtColor);\n        mLongPressTxtColor = getColor(R.color.color_minorView_longPressTxtColor);\n        mMacdBuyColor = getColor(R.color.color_minorView_macdBuyColor);\n        mMacdSellColor = getColor(R.color.color_minorView_macdSellColor);\n        mMacdDifColor = getColor(R.color.color_minorView_macdDifColor);\n        mMacdDeaColor = getColor(R.color.color_minorView_macdDeaColor);\n        mMacdMacdColor = getColor(R.color.color_minorView_macdMacdColor);\n        mRsi6Color = getColor(R.color.color_minorView_rsi6Color);\n        mRsi12Color = getColor(R.color.color_minorView_rsi12Color);\n        mRsi24Color = getColor(R.color.color_minorView_rsi24Color);\n        mKColor = getColor(R.color.color_minorView_kColor);\n        mDColor = getColor(R.color.color_minorView_dColor);\n        mJColor = getColor(R.color.color_minorView_jColor);\n    }\n\n    private void initListener() {\n        mVolListener = new KViewListener.MinorListener() {\n            @Override\n            public void masterLongPressListener(int pressIndex, Quotes currQuotes) {\n                mDrawLongPress = true;\n                mCurrLongPressQuotes = mQuotesList.get(pressIndex);\n                invalidate();\n            }\n\n            @Override\n            public void masterNoLongPressListener() {\n                mDrawLongPress = false;\n                invalidate();\n            }\n\n            @Override\n            public void masteZoomlNewIndex(int beginIndex, int endIndex, int shownMaxCount) {\n                mBeginIndex = beginIndex;\n                mEndIndex = endIndex;\n                mShownMaxCount = shownMaxCount;\n                seekAndCalculateCellData();\n            }\n\n            @Override\n            public void mastelPullmNewIndex(int beginIndex, int endIndex, KViewType.PullType currPullType, int shownMaxCount) {\n                mBeginIndex = beginIndex;\n                mEndIndex = endIndex;\n                mShownMaxCount = shownMaxCount;\n                mPullType = currPullType;\n\n                //处理右侧内边距\n                if (currPullType == KViewType.PullType.PULL_RIGHT_STOP) {\n                    //重置到之前的状态\n                    mInnerRightBlankPadding = DEF_INNER_RIGHT_BLANK_PADDING;\n                } else {\n                    mInnerRightBlankPadding = 0;\n                }\n\n                seekAndCalculateCellData();\n            }\n        };\n    }\n\n    private void drawLegend(Canvas canvas) {\n        //绘制非按下情况下图例\n        drawNoPressLegend(canvas);\n        //绘制按下的图例\n        drawPressLegend(canvas);\n    }\n\n    private void drawMinorIndicatrix(Canvas canvas) {\n        mMacdPaint.setStyle(Paint.Style.STROKE);\n        drawMACD(canvas);\n    }\n\n    private void drawLongPress(Canvas canvas) {\n        if (!mDrawLongPress) return;\n        if (mCurrLongPressQuotes == null) return;\n\n        //y轴线\n        canvas.drawLine(mCurrLongPressQuotes.floatX, mBasePaddingTop, mCurrLongPressQuotes.floatX,\n                mBaseHeight - mBasePaddingBottom, mLongPressPaint);\n    }\n\n    private void drawPressLegend(Canvas canvas) {\n        if (!mDrawLongPress) return;\n\n        mMacdPaint.setStyle(Paint.Style.FILL);\n        float x = (float) (mLegendPaddingLeft + mBasePaddingLeft);\n        float y = (float) (mLegendPaddingTop + mBasePaddingTop) + getFontHeight(mLegendTxtSize, mMacdPaint);\n\n        String showTxt = \"VOL:\" + FormatUtil.numFormat(mCurrLongPressQuotes.vol, mDigits) + \" \";\n        mMacdPaint.setColor(mMacdDifColor);\n        canvas.drawText(showTxt, x,\n                y, mMacdPaint);\n\n        float leftWidth11 = mMacdPaint.measureText(showTxt);\n        showTxt = \"MA5:\" + FormatUtil.numFormat(mCurrLongPressQuotes.volMa5, mDigits) + \" \";\n        mMacdPaint.setColor(mMacdDeaColor);\n        canvas.drawText(showTxt, x + leftWidth11, y, mMacdPaint);\n\n        float leftWidth12 = mMacdPaint.measureText(showTxt);\n        showTxt = \"MA10:\" + FormatUtil.numFormat(mCurrLongPressQuotes.volMa10, mDigits) + \" \";\n        mMacdPaint.setColor(mMacdMacdColor);\n        canvas.drawText(showTxt, (x + leftWidth11 + leftWidth12),\n                y, mMacdPaint);\n\n\n    }\n\n    private void drawNoPressLegend(Canvas canvas) {\n        if (mDrawLongPress) return;\n        String showTxt = \"MA(5，10)\";\n        canvas.drawText(showTxt,\n                (float) (mBaseWidth - mLegendPaddingRight - mBasePaddingRight - mLegendPaint.measureText(showTxt)),\n                (float) (mLegendPaddingTop + mBasePaddingTop + getFontHeight(mLegendTxtSize, mLegendPaint)), mLegendPaint);\n    }\n\n    private void drawYRightTxt(Canvas canvas) {\n        //绘制右侧的y轴文字\n        //现将最小值、最大值画好\n        float halfTxtHight = getFontHeight(mXYTxtSize, mXYTxtPaint) / 2;//应该/2的，但是不准确，原因不明\n        float x = mBaseWidth - mBasePaddingRight + mRightTxtPadding;\n        float maxY = mBasePaddingTop + halfTxtHight + mInnerTopBlankPadding;\n        float minY = mBaseHeight - mBasePaddingBottom - halfTxtHight - mInnerBottomBlankPadding;\n        //draw min\n        canvas.drawText(FormatUtil.numFormat(mMinY, mDigits),\n                x,\n                minY, mXYTxtPaint);\n        //draw max\n        canvas.drawText(FormatUtil.numFormat(mMaxY, mDigits),\n                x,\n                maxY, mXYTxtPaint);\n        //draw middle\n        canvas.drawText(FormatUtil.numFormat((mMaxY + mMinY) / 2.0, mDigits),\n                x, (minY + maxY) / 2.0f,\n                mXYTxtPaint);\n    }\n\n    private void drawMACD(Canvas canvas) {\n\n        //macd\n        //首先寻找\"0\"点，这个点是正负macd的分界点\n        float v = mBaseHeight - mBasePaddingBottom - mInnerBottomBlankPadding;\n        float startX, startY, stopX, stopY;\n\n        //dif\n        float difX, difY;\n        Path difPath = new Path();\n        //dea\n        float deaX, deaY;\n        Path deaPath = new Path();\n\n        boolean isFirstMa5 = true;\n        boolean isFirstMa10 = true;\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n\n            /*macd*/\n            //找另外一个y点\n            double y = v - mPerY * (quotes.vol - mMinY);\n            startX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mCandleDiverWidthRatio * mPerX / 2;\n            stopX = mBasePaddingLeft + (i - mBeginIndex + 1) * mPerX - mCandleDiverWidthRatio * mPerX / 2;\n            startY = v;\n            stopY = (float) y;\n            if (i > 0 && mQuotesList.get(i - 1).c < quotes.c) {\n                mMacdPaint.setColor(mMacdBuyColor);\n            } else {\n                mMacdPaint.setColor(mMacdSellColor);\n            }\n            //            Log.e(TAG, \"drawMACD: \"+startY+\",\"+stopY +\n            //                    \",\"+(mBasePaddingTop+mInnerTopBlankPadding)+\",\"+\n            //                    (mBaseHeight-mBasePaddingBottom-mInnerBottomBlankPadding));\n            mMacdPaint.setStyle(Paint.Style.FILL);\n            canvas.drawRect(startX, startY, stopX, stopY, mMacdPaint);\n\n\n            /*dif*/\n            difX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            difY = getMasterDetailFloatY(quotes, KViewType.MaType.volMa5);\n            if (difY != -1) {\n                if (isFirstMa5) {\n                    isFirstMa5 = false;\n                    if (quotes.volMa5 != 0) difX -= mPerX / 2;//第一个点特殊处理\n                    difPath.moveTo(difX, difY);\n                } else {\n                    if (i == mEndIndex - 1) difX += mPerX / 2;//最后一个点特殊处理\n                    difPath.lineTo(difX, difY);\n                }\n                mMacdPaint.setStyle(Paint.Style.STROKE);\n                mMacdPaint.setColor(mMacdDifColor);\n                canvas.drawPath(difPath, mMacdPaint);\n            }\n\n\n            /*dea*/\n            deaX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            deaY = getMasterDetailFloatY(quotes, KViewType.MaType.volMa10);\n            if (deaY != -1) {\n                if (isFirstMa10) {\n                    isFirstMa10 = false;\n                    if (quotes.volMa10 != 0) deaX -= mPerX / 2;//第一个点特殊处理\n                    deaPath.moveTo(deaX, deaY);\n                } else {\n                    if (i == mEndIndex - 1) deaX += mPerX / 2;//最后一个点特殊处理\n                    deaPath.lineTo(deaX, deaY);\n                }\n                mMacdPaint.setStyle(Paint.Style.STROKE);\n                mMacdPaint.setColor(mMacdDeaColor);\n                canvas.drawPath(deaPath, mMacdPaint);\n            }\n        }\n\n    }\n\n    private float getMasterDetailFloatY(Quotes quotes, KViewType.MaType maType) {\n        double v = 0;\n        //ma\n        if (maType == KViewType.MaType.volMa5) {\n            v = quotes.volMa5 - mMinY;\n        } else if (maType == KViewType.MaType.volMa10) {\n            v = quotes.volMa10 - mMinY;\n        }\n        //异常，当不存在ma值时的处理.也就是up、mb、dn为0时，这样判断其实有问题，比如算出来的值就是0？？？\n        if (v + mMinY == 0) return -1;\n\n        double h = v * mPerY;\n        float y = (float) (mBaseHeight - h - mBasePaddingBottom - mInnerBottomBlankPadding);\n\n        //这里的y,存在一种情况，y超过了View的上边界或者超过了下边界，当出现这一种情况时，不显示，当作异常情况\n        if (y < mBasePaddingTop || y > mBaseHeight - mBasePaddingBottom)\n            return -1;\n\n        return y;\n    }\n\n    private void drawRSI(Canvas canvas) {\n\n        float rsiX;\n\n        //rsi6\n        float rsi6Y;\n        Path rsi6Path = new Path();\n\n        //rsi12\n        float rsi12Y;\n        Path rsi12Path = new Path();\n\n        //rsi24\n        float rsi24Y;\n        Path rsi24Path = new Path();\n\n        float v = mBaseHeight - mBasePaddingBottom - mInnerBottomBlankPadding;\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n\n            /*rsi6*/\n            rsiX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            rsi6Y = (float) (v - mPerY * (quotes.rsi6 - mMinY));\n            if (i == mBeginIndex) {\n                rsi6Path.moveTo(rsiX - mPerX / 2, rsi6Y);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    rsiX += mPerX / 2;//最后一个点特殊处理\n                }\n                rsi6Path.lineTo(rsiX, rsi6Y);\n            }\n            mRsiPaint.setColor(mRsi6Color);\n            canvas.drawPath(rsi6Path, mRsiPaint);\n\n            /*rsi12*/\n            //为什么这里重复再赋一遍值？因为下面有一个\"rsiX +=\"操作\n            rsiX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            rsi12Y = (float) (v - mPerY * (quotes.rsi12 - mMinY));\n            if (i == mBeginIndex) {\n                rsi12Path.moveTo(rsiX - mPerX / 2, rsi12Y);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    rsiX += mPerX / 2;//最后一个点特殊处理\n                }\n                rsi12Path.lineTo(rsiX, rsi12Y);\n            }\n            mRsiPaint.setColor(mRsi12Color);\n            canvas.drawPath(rsi12Path, mRsiPaint);\n\n            /*rsi24*/\n            //为什么这里重复再赋一遍值？因为下面有一个\"rsiX +=\"操作\n            rsiX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            rsi24Y = (float) (v - mPerY * (quotes.rsi24 - mMinY));\n            if (i == mBeginIndex) {\n                rsi24Path.moveTo(rsiX - mPerX / 2, rsi24Y);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    rsiX += mPerX / 2;//最后一个点特殊处理\n                }\n                rsi24Path.lineTo(rsiX, rsi24Y);\n            }\n            mRsiPaint.setColor(mRsi24Color);\n            canvas.drawPath(rsi24Path, mRsiPaint);\n\n        }\n    }\n\n    private void drawKDJ(Canvas canvas) {\n\n        float kdjX;\n\n        //k\n        float kY;\n        Path kPath = new Path();\n\n        //d\n        float dY;\n        Path dPath = new Path();\n\n        //j\n        float jY;\n        Path jPath = new Path();\n\n        float v = mBaseHeight - mBasePaddingBottom - mInnerBottomBlankPadding;\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n\n            /*k*/\n            kdjX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            kY = (float) (v - mPerY * (quotes.k - mMinY));\n            if (i == mBeginIndex) {\n                kPath.moveTo(kdjX - mPerX / 2, kY);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    kdjX += mPerX / 2;//最后一个点特殊处理\n                }\n                kPath.lineTo(kdjX, kY);\n            }\n            mKdjPaint.setColor(mKColor);\n            canvas.drawPath(kPath, mKdjPaint);\n\n            /*d*/\n            kdjX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            dY = (float) (v - mPerY * (quotes.d - mMinY));\n            if (i == mBeginIndex) {\n                dPath.moveTo(kdjX - mPerX / 2, dY);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    kdjX += mPerX / 2;//最后一个点特殊处理\n                }\n                dPath.lineTo(kdjX, dY);\n            }\n            mKdjPaint.setColor(mDColor);\n            canvas.drawPath(dPath, mKdjPaint);\n\n            /*j*/\n            kdjX = mBasePaddingLeft + (i - mBeginIndex) * mPerX + mPerX / 2;\n            jY = (float) (v - mPerY * (quotes.j - mMinY));\n            if (i == mBeginIndex) {\n                jPath.moveTo(kdjX - mPerX / 2, jY);//第一个点特殊处理\n            } else {\n                if (i == mEndIndex - 1) {\n                    kdjX += mPerX / 2;//最后一个点特殊处理\n                }\n                jPath.lineTo(kdjX, jY);\n            }\n            mKdjPaint.setColor(mJColor);\n            canvas.drawPath(jPath, mKdjPaint);\n\n        }\n    }\n\n    @Override\n    protected void seekAndCalculateCellData() {\n        if (mQuotesList == null || mQuotesList.isEmpty()) return;\n        if (!isShowVol()) return;\n\n        FinancialAlgorithm.calculateMA(mQuotesList, 5, KViewType.MaType.volMa5);\n        FinancialAlgorithm.calculateMA(mQuotesList, 10, KViewType.MaType.volMa10);\n\n\n        //找到close最大值和最小值\n        mMinY = Integer.MAX_VALUE;\n        mMaxY = Integer.MIN_VALUE;\n\n\n        for (int i = mBeginIndex; i < mEndIndex; i++) {\n            Quotes quotes = mQuotesList.get(i);\n            if (i == mBeginIndex) {\n                mBeginQuotes = quotes;\n            }\n            if (i == mEndIndex - 1) {\n                mEndQuotes = quotes;\n            }\n            double min = FinancialAlgorithm.getVolMinY(quotes);\n            double max = FinancialAlgorithm.getVolMaxY(quotes);\n\n            if (min <= mMinY) {\n                mMinY = min;\n            }\n            if (max >= mMaxY) {\n                mMaxY = max;\n            }\n\n        }\n\n\n        mPerX = (mBaseWidth - mBasePaddingLeft - mBasePaddingRight - mInnerRightBlankPadding)\n                / (mShownMaxCount);\n        //不要忘了减去内部的上下Padding\n        mPerY = (float) ((mBaseHeight - mBasePaddingTop - mBasePaddingBottom - mInnerTopBlankPadding\n                - mInnerBottomBlankPadding) / (mMaxY - mMinY));\n        Log.e(TAG, \"seekAndCalculateCellData: mMinY：\" + mMinY + \",mMaxY:\" + mMaxY);\n        //重绘\n        invalidate();\n    }\n\n    @Override\n    protected void innerClickListener() {\n        super.innerClickListener();\n        if (mMinorType == KViewType.MinorIndicatrixType.MACD) {\n            mMinorType = KViewType.MinorIndicatrixType.RSI;\n        } else if (mMinorType == KViewType.MinorIndicatrixType.RSI) {\n            mMinorType = KViewType.MinorIndicatrixType.KDJ;\n        } else if (mMinorType == KViewType.MinorIndicatrixType.KDJ) {\n            mMinorType = KViewType.MinorIndicatrixType.MACD;\n        }\n        setMinorType(mMinorType);\n    }\n\n    @Override\n    protected void innerLongClickListener(float x, float y) {\n        super.innerLongClickListener(x, y);\n\n    }\n\n    @Override\n    protected void innerHiddenLongClick() {\n        super.innerHiddenLongClick();\n    }\n\n    @Override\n    protected void innerMoveViewListener(float moveXLen) {\n        super.innerMoveViewListener(moveXLen);\n\n    }\n\n\n    //-----------------------对开发者暴露可以修改的参数-------\n\n    public void setMinorType(KViewType.MinorIndicatrixType minorType) {\n        mMinorType = minorType;\n\n        seekAndCalculateCellData();\n    }\n\n    public int getOuterStrokeColor() {\n        return mOuterStrokeColor;\n    }\n\n    public VolView setOuterStrokeColor(int outerStrokeColor) {\n        mOuterStrokeColor = outerStrokeColor;\n        return this;\n    }\n\n    public int getInnerXyDashColor() {\n        return mInnerXyDashColor;\n    }\n\n    public VolView setInnerXyDashColor(int innerXyDashColor) {\n        mInnerXyDashColor = innerXyDashColor;\n        return this;\n    }\n\n    public int getXyTxtColor() {\n        return mXyTxtColor;\n    }\n\n    public VolView setXyTxtColor(int xyTxtColor) {\n        mXyTxtColor = xyTxtColor;\n        return this;\n    }\n\n    public int getLegendTxtColor() {\n        return mLegendTxtColor;\n    }\n\n    public VolView setLegendTxtColor(int legendTxtColor) {\n        mLegendTxtColor = legendTxtColor;\n        return this;\n    }\n\n    public int getLongPressTxtColor() {\n        return mLongPressTxtColor;\n    }\n\n    public VolView setLongPressTxtColor(int longPressTxtColor) {\n        mLongPressTxtColor = longPressTxtColor;\n        return this;\n    }\n\n    public int getMacdBuyColor() {\n        return mMacdBuyColor;\n    }\n\n    public VolView setMacdBuyColor(int macdBuyColor) {\n        mMacdBuyColor = macdBuyColor;\n        return this;\n    }\n\n    public int getMacdSellColor() {\n        return mMacdSellColor;\n    }\n\n    public VolView setMacdSellColor(int macdSellColor) {\n        mMacdSellColor = macdSellColor;\n        return this;\n    }\n\n    public int getMacdDifColor() {\n        return mMacdDifColor;\n    }\n\n    public VolView setMacdDifColor(int macdDifColor) {\n        mMacdDifColor = macdDifColor;\n        return this;\n    }\n\n    public int getMacdDeaColor() {\n        return mMacdDeaColor;\n    }\n\n    public VolView setMacdDeaColor(int macdDeaColor) {\n        mMacdDeaColor = macdDeaColor;\n        return this;\n    }\n\n    public int getMacdMacdColor() {\n        return mMacdMacdColor;\n    }\n\n    public VolView setMacdMacdColor(int macdMacdColor) {\n        mMacdMacdColor = macdMacdColor;\n        return this;\n    }\n\n    public Paint getMacdPaint() {\n        return mMacdPaint;\n    }\n\n    public VolView setMacdPaint(Paint macdPaint) {\n        mMacdPaint = macdPaint;\n        return this;\n    }\n\n    public float getMacdLineWidth() {\n        return mMacdLineWidth;\n    }\n\n    public VolView setMacdLineWidth(float macdLineWidth) {\n        mMacdLineWidth = macdLineWidth;\n        return this;\n    }\n\n    public int getRsi6Color() {\n        return mRsi6Color;\n    }\n\n    public VolView setRsi6Color(int rsi6Color) {\n        mRsi6Color = rsi6Color;\n        return this;\n    }\n\n    public int getRsi12Color() {\n        return mRsi12Color;\n    }\n\n    public VolView setRsi12Color(int rsi12Color) {\n        mRsi12Color = rsi12Color;\n        return this;\n    }\n\n    public int getRsi24Color() {\n        return mRsi24Color;\n    }\n\n    public VolView setRsi24Color(int rsi24Color) {\n        mRsi24Color = rsi24Color;\n        return this;\n    }\n\n    public Paint getRsiPaint() {\n        return mRsiPaint;\n    }\n\n    public VolView setRsiPaint(Paint rsiPaint) {\n        mRsiPaint = rsiPaint;\n        return this;\n    }\n\n    public float getRsiLineWidth() {\n        return mRsiLineWidth;\n    }\n\n    public VolView setRsiLineWidth(float rsiLineWidth) {\n        mRsiLineWidth = rsiLineWidth;\n        return this;\n    }\n\n    public int getKColor() {\n        return mKColor;\n    }\n\n    public VolView setKColor(int KColor) {\n        mKColor = KColor;\n        return this;\n    }\n\n    public int getDColor() {\n        return mDColor;\n    }\n\n    public VolView setDColor(int DColor) {\n        mDColor = DColor;\n        return this;\n    }\n\n    public int getJColor() {\n        return mJColor;\n    }\n\n    public VolView setJColor(int JColor) {\n        mJColor = JColor;\n        return this;\n    }\n\n    public Paint getKdjPaint() {\n        return mKdjPaint;\n    }\n\n    public VolView setKdjPaint(Paint kdjPaint) {\n        mKdjPaint = kdjPaint;\n        return this;\n    }\n\n    public float getKdjLineWidth() {\n        return mKdjLineWidth;\n    }\n\n    public VolView setKdjLineWidth(float kdjLineWidth) {\n        mKdjLineWidth = kdjLineWidth;\n        return this;\n    }\n\n    public KViewType.MinorIndicatrixType getMinorType() {\n        return mMinorType;\n    }\n\n    public double getMinY() {\n        return mMinY;\n    }\n\n    public VolView setMinY(double minY) {\n        mMinY = minY;\n        return this;\n    }\n\n    public double getMaxY() {\n        return mMaxY;\n    }\n\n    public VolView setMaxY(double maxY) {\n        mMaxY = maxY;\n        return this;\n    }\n\n    public float getCandleDiverWidthRatio() {\n        return mCandleDiverWidthRatio;\n    }\n\n    public VolView setCandleDiverWidthRatio(float candleDiverWidthRatio) {\n        mCandleDiverWidthRatio = candleDiverWidthRatio;\n        return this;\n    }\n\n    public VolView setVolListener(KViewListener.MinorListener volListener) {\n        mVolListener = volListener;\n        return this;\n    }\n\n    public KViewListener.MinorListener getVolListener() {\n        return mVolListener;\n    }\n\n    public boolean isShowVol() {\n        return mShowVol;\n    }\n\n    public VolView setShowVol(boolean showVol) {\n        mShowVol = showVol;\n        return this;\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/pie/PieChartAnimation.java",
    "content": "package com.tophold.trade.view.pie;\n\nimport android.util.Log;\nimport android.view.animation.Animation;\nimport android.view.animation.Transformation;\n\nimport com.tophold.trade.utils.StringUtils;\n\nimport java.util.List;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/07/17 16:50\n * 描 述 ：\n * ============================================================\n */\npublic class PieChartAnimation extends Animation {\n    public static final String TAG = PieChartAnimation.class.getSimpleName();\n    List<PieEntrys> mPieEntrysList;\n    float mSumValue;\n    PieChartView mView;\n\n    public void setPieChartData(List<PieEntrys> pieEntrysList, float sumValue, PieChartView view) {\n        this.mPieEntrysList = pieEntrysList;\n        this.mSumValue = sumValue;\n        this.mView = view;\n    }\n\n    @Override\n    protected void applyTransformation(float interpolatedTime, Transformation t) {\n        super.applyTransformation(interpolatedTime, t);\n        if (StringUtils.isEmpty(mPieEntrysList) || mSumValue <= 0 || mView == null) return;\n        Log.d(TAG, \"applyTransformation1: \" + interpolatedTime);\n        if (interpolatedTime == 1.0f) {\n            mView.setDrawLine(true);\n        }\n        for (int i = 0; i < mPieEntrysList.size(); i++) {\n            PieEntrys data = mPieEntrysList.get(i);\n            //通过总和来计算百分比\n            float percentage = data.value / mSumValue;\n            //通过百分比来计算对应的角度\n            float angle = percentage * 360;\n            //根据插入时间来计算角度\n            angle = angle * interpolatedTime;\n            data.mSweepAngle = angle;\n        }\n        mView.invalidate();\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/pie/PieChartView.java",
    "content": "package com.tophold.trade.view.pie;\n\nimport android.content.Context;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.Paint;\nimport android.graphics.RectF;\nimport android.support.annotation.Nullable;\nimport android.support.v4.content.ContextCompat;\nimport android.util.AttributeSet;\nimport android.util.Log;\n\nimport com.tophold.trade.R;\nimport com.tophold.trade.utils.GsonUtil;\nimport com.tophold.trade.utils.ScreenUtils;\nimport com.tophold.trade.utils.StringUtils;\nimport com.tophold.trade.view.BaseView;\n\n\nimport java.util.List;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/07/10 20:40\n * 描 述 ：对饼形图实现给出一个思路。之前看MP实现如果改成这样可能比较麻烦一点，这里就直接进行是实现。\n * 饼形图的实现难点不在于图的实现，而在于图周围的指示文字的控制，如果处理不好就会出现挤压问题。这里的处理思路是：给出最小比例，\n * 如果小于这个比例直接从最大份中\"借\"出一点满足最小比例。\n * ============================================================\n */\npublic class PieChartView extends BaseView {\n\n    public static final float DEF_PARTSTHRESHOLD = 0.1f;\n\n    List<PieEntrys> mPieEntryList;\n\n    /**\n     * 内边距\n     */\n    float basePaddingTop = 45;\n    float basePaddingBottom = 45;\n    float basePaddingLeft;\n    float basePaddingRight;\n\n    //内部圆洞的半径\n    float holdRadius = 40;\n    //高亮环的宽度\n    float highLightWidth = 4;\n    //高亮环距离圆环的距离\n    float highLightPadding = 5;\n\n    //指示线距离圆环的边距\n    float lineLengthMargin = 10;\n    //指示线延伸长度\n    float lineLength = 85;\n    //指示线的宽度\n    float lineWidth = 1f;\n    //是否延伸长度的阀值\n    float lineThreshold = 10;\n    //延长的宽度\n    float lineThresholdLength = 50;\n\n    //指示文字下边距\n    float textPaddingBottom = 2;\n    //圆点半径\n    float dotRadius = 2;\n\n    //上下两个txt之间的y轴的距离\n    float txtThresholdmargin = 20;\n    //上下两个txt之间的y轴的阀值\n    float txtThreshold = 20;\n\n    //文字大小\n    float textSize = 12;\n    //饼图item最小的占比。0~1，定义最小的item,防止积压在一起。初始值设置小一点，为了动画好看。\n    float minPartsThreshold = DEF_PARTSTHRESHOLD;\n\n\n    //没有数据显示\n    String mEmptyTxt = \"还没有交易哦\";\n\n    //开始角度\n    float mBeginAngle = -90;\n\n    /**\n     * 自定义动画\n     */\n    private PieChartAnimation mAnimation;\n    long mAnim = 1000;\n\n    //私有属性，不对外暴露\n    private float centerX;\n    private float centerY;\n    private boolean firstCome = true;\n\n    boolean mDrawLine = false;\n\n\n    public PieChartView(Context context) {\n        this(context, null);\n    }\n\n    public PieChartView(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public PieChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        initAttrs();\n    }\n\n    private void initAttrs() {\n        mAnimation = new PieChartAnimation();\n        mAnimation.setDuration(mAnim);\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n    }\n\n    /**\n     * 所有单位传递标准化参数即可，这里进行转换。\n     */\n    private void allDp2Px() {\n        if (!firstCome) return;\n        firstCome = false;\n\n        basePaddingLeft = ScreenUtils.dip2px(basePaddingLeft);\n        basePaddingRight = ScreenUtils.dip2px(basePaddingRight);\n        basePaddingTop = ScreenUtils.dip2px(basePaddingTop);\n        basePaddingBottom = ScreenUtils.dip2px(basePaddingBottom);\n        highLightWidth = ScreenUtils.dip2px(highLightWidth);\n        highLightPadding = ScreenUtils.dip2px(highLightPadding);\n        holdRadius = ScreenUtils.dip2px(holdRadius);\n        lineLength = ScreenUtils.dip2px(lineLength);\n        lineWidth = ScreenUtils.dip2px(lineWidth);\n        dotRadius = ScreenUtils.dip2px(dotRadius);\n        textSize = ScreenUtils.sp2px(textSize);\n        textPaddingBottom = ScreenUtils.dip2px(textPaddingBottom);\n        lineThreshold = ScreenUtils.dip2px(lineThreshold);\n        lineThresholdLength = ScreenUtils.dip2px(lineThresholdLength);\n        txtThreshold = ScreenUtils.dip2px(txtThreshold);\n        txtThresholdmargin = ScreenUtils.dip2px(txtThresholdmargin);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n\n        allDp2Px();\n\n        centerX = getBaseWidth() / 2.0f;\n        centerY = getBaseHeight() / 2.0f;\n\n\n        drawCircle(canvas);\n    }\n\n\n    private void initPieData() {\n        if (StringUtils.isEmptyList(mPieEntryList)) {\n            return;\n        }\n        float sumValue = 0;\n        int maxIndex = 0;\n        float maxData = -1;\n        //数据预处理:对占比比较小的值多分配一点防止太小。\n        for (int i = 0; i < mPieEntryList.size(); i++) {\n            PieEntrys pieEntry = mPieEntryList.get(i);\n            sumValue += pieEntry.value;\n            if (pieEntry.value > maxData) {\n                maxData = pieEntry.value;\n                maxIndex = i;\n            }\n        }\n        mAnimation.setPieChartData(mPieEntryList, sumValue, this);\n        /**\n         * 边界问题处理：防止item太小,出现文字积压问题。\n         */\n        PieEntrys maxPieEntry = mPieEntryList.get(maxIndex);\n        for (int i = 0; i < mPieEntryList.size(); i++) {\n            PieEntrys pieEntry = mPieEntryList.get(i);\n            float tempValue = pieEntry.value;\n            if (pieEntry.value / sumValue < minPartsThreshold) {\n                //该块补全最小值\n                pieEntry.value = sumValue * minPartsThreshold;\n                float disLen = pieEntry.value - tempValue;\n                //最大块减去被减去的\n                maxPieEntry.value -= disLen;\n            }\n        }\n\n        //startAnimation的时候，如果这个View是不可见的，或者是gone的，就会导致传进去的Animation对象不执行\n        postDelayed(() -> startAnimation(mAnimation), 300);\n    }\n\n    private void drawCircle(Canvas canvas) {\n        if (StringUtils.isEmptyList(mPieEntryList)) {\n            drawEmptyView(canvas);\n            return;\n        }\n\n        //正式开始处理\n        float valueW = getBaseWidth() - basePaddingLeft - basePaddingRight;\n        float valueH = getBaseHeight() - basePaddingTop - basePaddingBottom;\n        float radius = Math.min(valueW,\n                valueH) / 2.0f;\n        float lX = centerX - radius;\n        float tY = centerY - radius;\n        float rX = centerX + radius;\n        float bY = centerY + radius;\n        //圆环外边界，但是如果圆环成整个圆之后，就是内边界了。\n        RectF rectF = new RectF(lX, tY, rX, bY);\n        float beginAngle = mBeginAngle;\n        float preYpos = 0;\n        for (PieEntrys pieEntry : mPieEntryList) {\n\n            //无动画\n            //float sweepAngle = 360 * pieEntry.value / mSumValue;\n            //在这里实现动画\n            float sweepAngle = pieEntry.mSweepAngle;\n\n            //防止item过小\n            if (sweepAngle < 360 * minPartsThreshold) {\n                sweepAngle = 360 * minPartsThreshold;\n            }\n            //防止绘制过度\n            if (beginAngle + sweepAngle > 270) {\n                sweepAngle = 270 - beginAngle;\n            }\n\n            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n            paint.setStyle(Paint.Style.FILL);\n            //paint.setStrokeWidth(roundWidth);\n            paint.setColor(pieEntry.colorBg);\n            canvas.drawArc(rectF, beginAngle, sweepAngle, true, paint);\n            //高亮逻辑\n            if (pieEntry.highLight) {\n                float radius2 = Math.min(\n                        valueW,\n                        valueH) / 2.0f + highLightPadding + highLightWidth / 2.0f;\n\n                float lX2 = centerX - radius2;\n                float tY2 = centerY - radius2;\n                float rX2 = centerX + radius2;\n                float bY2 = centerY + radius2;\n\n                RectF rectF2 = new RectF(lX2, tY2, rX2, bY2);\n                Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);\n                paint2.setStyle(Paint.Style.STROKE);\n                paint2.setStrokeWidth(highLightWidth);\n                paint2.setColor(pieEntry.colorBg);\n                canvas.drawArc(rectF2, beginAngle, sweepAngle, false, paint2);\n            }\n\n            if (mDrawLine) {\n                /**\n                 * 指示文字，重要逻辑\n                 * 思路：取该模块的度数的中间值向外延伸一定距离。如果该度数在[-90,90]之间，在右边显示；否则在左边显示。\n                 */\n                //真实的角度\n                float coreAngle = beginAngle + sweepAngle / 2.0f;//因为从-90开始的\n                float r = radius;//圆的半径\n\n                Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n                linePaint.setColor(pieEntry.colorBg);\n                linePaint.setStrokeWidth(lineWidth);\n\n                Paint ratePaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n                ratePaint.setColor(pieEntry.highLight ? getColor(R.color.color_pie_chart_red) : getColor(R.color.color_pie_chart_gray));\n                ratePaint.setTextSize(textSize);\n\n                Paint symbolPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n                symbolPaint.setColor(getColor(R.color.color_pie_chart_gray));\n                symbolPaint.setTextSize(textSize);\n\n\n                float yPos;\n                //右边\n                //Log.d(TAG, \"drawCircle: \" + coreAngle);\n                float textPdding = getFontHeight(textSize, ratePaint);\n                if (coreAngle >= -90 && coreAngle <= 90) {\n                    float circleX = centerX + radius + highLightPadding + highLightWidth;\n                    float xPos = circleX + lineLengthMargin;//x的坐标\n                    boolean isThreshold = false;\n                    if (coreAngle <= 0) {\n                        yPos = (float) (centerY - Math.cos(getAreaAngle(90 + coreAngle)) * r);//y的左边\n                        //在上边界或者下边界x方向延伸长一点\n                        if (r - (centerY - yPos) < lineThreshold) {\n                            xPos -= lineThresholdLength;\n                            isThreshold = true;\n                        }\n                    } else {\n                        yPos = (float) (centerY + Math.cos(getAreaAngle(90 - coreAngle)) * r);//y的左边\n                        //在上边界或者下边界x方向延伸长一点\n                        if (r - (yPos - centerY) < lineThreshold) {\n                            xPos -= lineThresholdLength;\n                            isThreshold = true;\n                        }\n                    }\n\n                    //又一个边界问题\n                    if (preYpos != 0 && yPos - preYpos < txtThreshold) {\n                        yPos += txtThresholdmargin;\n                    }\n                    preYpos = yPos;\n\n                    //Log.d(TAG, \"drawCircle: \" + xPos + \",\" + yPos);\n                    float lineLeft = !isThreshold ? xPos + lineLength : xPos + lineLength + lineThresholdLength;\n                    float txtLeft = !isThreshold ? xPos : xPos + lineThresholdLength;\n                    canvas.drawLine(xPos, yPos, lineLeft, yPos, linePaint);\n                    canvas.drawCircle(xPos, yPos, dotRadius, linePaint);\n                    float labelLen = lineLength - ratePaint.measureText(pieEntry.label);\n                    canvas.drawText(pieEntry.label, txtLeft + labelLen, yPos - textPaddingBottom, ratePaint);\n                    float symbolLen = lineLength - symbolPaint.measureText(pieEntry.symbol);\n                    canvas.drawText(pieEntry.symbol, txtLeft + symbolLen, yPos + textPaddingBottom + textPdding / 2.0f, symbolPaint);\n                } else {\n                    float circleX = centerX - radius - highLightPadding - highLightWidth;\n                    float xPos = circleX + lineLengthMargin;//x的坐标\n                    boolean isThreshold = false;\n                    //左边\n                    if (coreAngle <= 180) {\n                        yPos = (float) (centerY + Math.cos(getAreaAngle(coreAngle - 90)) * r);//y的左边\n                        //在上边界或者下边界x方向延伸长一点\n                        if (r - (yPos - centerY) < lineThreshold) {\n                            xPos += lineThresholdLength;\n                            isThreshold = true;\n                        }\n                    } else {\n                        yPos = (float) (centerY - Math.cos(getAreaAngle(270 - coreAngle)) * r);//y的左边\n                        if (r - (centerY - yPos) < lineThreshold) {\n                            xPos += lineThresholdLength;\n                            isThreshold = true;\n                        }\n                    }\n\n                    //又一个边界问题\n                    if (preYpos != 0 && preYpos - yPos < txtThreshold) {\n                        yPos -= txtThresholdmargin;\n                    }\n                    preYpos = yPos;\n\n                    //Log.d(TAG, \"drawCircle: \" + xPos + \",\" + yPos);\n                    float lineLeft = !isThreshold ? xPos - lineLength : xPos - lineLength - lineThresholdLength;\n                    float txtLeft = !isThreshold ? xPos - lineLength : xPos - lineLength - lineThresholdLength;\n\n                    canvas.drawLine(xPos, yPos, lineLeft, yPos, linePaint);\n                    canvas.drawCircle(xPos, yPos, dotRadius, linePaint);\n                    canvas.drawText(pieEntry.label, txtLeft, yPos - textPaddingBottom, ratePaint);\n                    canvas.drawText(pieEntry.symbol, txtLeft, yPos + textPaddingBottom + textPdding / 2.0f, symbolPaint);\n                }\n            }\n            beginAngle += sweepAngle;\n        }\n\n        //最后绘制中间的圆洞\n        Paint holdPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        holdPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_minorView_longPressTxtColor));\n        canvas.drawCircle(centerX, centerY, holdRadius, holdPaint);\n\n    }\n\n    private float getAreaAngle(float angle) {\n        return (float) (Math.PI * angle / 180);\n    }\n\n    private void drawEmptyView(Canvas canvas) {\n        String txt = mEmptyTxt;\n        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        paint.setTextSize(ScreenUtils.sp2px(15));\n        paint.setColor(getColor(R.color.color_pie_chart_gray));\n        canvas.drawText(txt, getBaseWidth() / 2.0f - paint.measureText(txt) / 2.0f, getBaseHeight() / 2.0f, paint);\n    }\n\n    public List<PieEntrys> getPieEntryList() {\n        return mPieEntryList;\n    }\n\n    public PieChartView setPieEntryList(List<PieEntrys> pieEntryList) {\n        mPieEntryList = pieEntryList;\n        initPieData();\n        return this;\n    }\n\n    public float getBasePaddingTop() {\n        return basePaddingTop;\n    }\n\n    public PieChartView setBasePaddingTop(float basePaddingTop) {\n        this.basePaddingTop = basePaddingTop;\n        return this;\n    }\n\n    public float getBasePaddingBottom() {\n        return basePaddingBottom;\n    }\n\n    public PieChartView setBasePaddingBottom(float basePaddingBottom) {\n        this.basePaddingBottom = basePaddingBottom;\n        return this;\n    }\n\n    public float getBasePaddingLeft() {\n        return basePaddingLeft;\n    }\n\n    public PieChartView setBasePaddingLeft(float basePaddingLeft) {\n        this.basePaddingLeft = basePaddingLeft;\n        return this;\n    }\n\n    public float getBasePaddingRight() {\n        return basePaddingRight;\n    }\n\n    public PieChartView setBasePaddingRight(float basePaddingRight) {\n        this.basePaddingRight = basePaddingRight;\n        return this;\n    }\n\n    public float getHighLightWidth() {\n        return highLightWidth;\n    }\n\n    public PieChartView setHighLightWidth(float highLightWidth) {\n        this.highLightWidth = highLightWidth;\n        return this;\n    }\n\n    public float getHighLightPadding() {\n        return highLightPadding;\n    }\n\n    public PieChartView setHighLightPadding(float highLightPadding) {\n        this.highLightPadding = highLightPadding;\n        return this;\n    }\n\n    public float getLineLengthMargin() {\n        return lineLengthMargin;\n    }\n\n    public PieChartView setLineLengthMargin(float lineLengthMargin) {\n        this.lineLengthMargin = lineLengthMargin;\n        return this;\n    }\n\n    public float getLineLength() {\n        return lineLength;\n    }\n\n    public PieChartView setLineLength(float lineLength) {\n        this.lineLength = lineLength;\n        return this;\n    }\n\n    public float getLineWidth() {\n        return lineWidth;\n    }\n\n    public PieChartView setLineWidth(float lineWidth) {\n        this.lineWidth = lineWidth;\n        return this;\n    }\n\n    public float getLineThreshold() {\n        return lineThreshold;\n    }\n\n    public PieChartView setLineThreshold(float lineThreshold) {\n        this.lineThreshold = lineThreshold;\n        return this;\n    }\n\n    public float getLineThresholdLength() {\n        return lineThresholdLength;\n    }\n\n    public PieChartView setLineThresholdLength(float lineThresholdLength) {\n        this.lineThresholdLength = lineThresholdLength;\n        return this;\n    }\n\n    public float getTextPaddingBottom() {\n        return textPaddingBottom;\n    }\n\n    public PieChartView setTextPaddingBottom(float textPaddingBottom) {\n        this.textPaddingBottom = textPaddingBottom;\n        return this;\n    }\n\n    public float getDotRadius() {\n        return dotRadius;\n    }\n\n    public PieChartView setDotRadius(float dotRadius) {\n        this.dotRadius = dotRadius;\n        return this;\n    }\n\n    public float getTxtThresholdmargin() {\n        return txtThresholdmargin;\n    }\n\n    public PieChartView setTxtThresholdmargin(float txtThresholdmargin) {\n        this.txtThresholdmargin = txtThresholdmargin;\n        return this;\n    }\n\n    public float getTxtThreshold() {\n        return txtThreshold;\n    }\n\n    public PieChartView setTxtThreshold(float txtThreshold) {\n        this.txtThreshold = txtThreshold;\n        return this;\n    }\n\n    public float getTextSize() {\n        return textSize;\n    }\n\n    public PieChartView setTextSize(float textSize) {\n        this.textSize = textSize;\n        return this;\n    }\n\n    public float getMinPartsThreshold() {\n        return minPartsThreshold;\n    }\n\n    public PieChartView setMinPartsThreshold(float minPartsThreshold) {\n        this.minPartsThreshold = minPartsThreshold;\n        return this;\n    }\n\n    public String getEmptyTxt() {\n        return mEmptyTxt;\n    }\n\n    public PieChartView setEmptyTxt(String emptyTxt) {\n        mEmptyTxt = emptyTxt;\n        return this;\n    }\n\n    public PieChartView setDrawLine(boolean drawLine) {\n        mDrawLine = drawLine;\n        return this;\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/pie/PieEntrys.java",
    "content": "package com.tophold.trade.view.pie;\n\nimport android.support.annotation.ColorInt;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/07/10 20:36\n * 描 述 ：\n * ============================================================\n */\npublic class PieEntrys {\n    public float value;\n    public String label;\n    @ColorInt\n    public int colorBg;\n    public boolean highLight;\n    public String symbol;\n\n    public PieEntrys(float value, String label, int colorBg, boolean highLight, String symbol) {\n        this.value = value;\n        this.label = label;\n        this.colorBg = colorBg;\n        this.highLight = highLight;\n        this.symbol = symbol;\n    }\n\n    //一些额外的字段辅助画图\n    //单个item需要扫过的角度\n    public float mSweepAngle;\n\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/seekbar/DoubleThumbSeekBar.java",
    "content": "package com.tophold.trade.view.seekbar;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport android.graphics.RectF;\nimport android.graphics.drawable.Drawable;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.MotionEvent;\n\n\nimport com.tophold.trade.utils.RenderUtils;\nimport com.tophold.trade.view.BaseView;\n\nimport java.util.Arrays;\n\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/11/30 14:00\n * 描 述 ：\n * ============================================================\n */\npublic class DoubleThumbSeekBar extends BaseView {\n\n    private DoubleTumb mDoubleThumb;\n\n    //背景相关\n    private Paint mBackgroudPaint;\n    private RectF mBackgroudRectF;\n\n    //seekbar四个顶点\n    private int[] mPostionArr;\n\n    //前景图1\n    private Paint mForegroundPaintA;\n    private RectF mForegroundRectFA;\n    private Bitmap mThumbBitmapA;\n    private Paint mTipPaintA;\n\n    //前景图2\n    private Paint mForegroundPaintB;\n    private RectF mForegroundRectFB;\n    private Bitmap mThumbBitmapB;\n    private Paint mTipPaintB;\n\n    //滑动监听\n    private OnDoubleThumbChangeListener mOnDoubleThumbChangeListener;\n\n    //是否拦截事件\n    private boolean mDisallowIntercept = false;\n\n    /**\n     * 设置监听\n     *\n     * @param onDoubleThumbChangeListener\n     */\n    public void setOnDoubleThumbChangeListener(OnDoubleThumbChangeListener onDoubleThumbChangeListener) {\n        mOnDoubleThumbChangeListener = onDoubleThumbChangeListener;\n    }\n\n\n    public DoubleThumbSeekBar(Context context) {\n        this(context, null);\n    }\n\n    public DoubleThumbSeekBar(Context context, @Nullable AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public DoubleThumbSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n    }\n\n    public void init(DoubleTumb doubleThumb) {\n        this.mDoubleThumb = doubleThumb;\n        initArrts();\n    }\n\n    private void initArrts() {\n        if (mDoubleThumb == null) {\n            throw new IllegalArgumentException(\"请先初始化:init(DoubleThumbSeekBar doubleThumbSeekBar)\");\n        }\n        initPaint();\n    }\n\n    private void initPaint() {\n        mBackgroudPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mBackgroudPaint.setColor(mDoubleThumb.mBackground);\n        mBackgroudPaint.setStyle(Paint.Style.FILL);\n        mBackgroudRectF = new RectF();\n\n        /**\n         * thumbA相关设置\n         */\n        mForegroundPaintA = new Paint(Paint.ANTI_ALIAS_FLAG);\n        Drawable foregroundDrawableA = mDoubleThumb.mThumbA.mForegroundDrawable;\n        if (foregroundDrawableA != null) {\n            // TODO: 03/12/2018\n        } else {\n            mForegroundPaintA.setColor(mDoubleThumb.mThumbA.mForeground);\n        }\n        mForegroundPaintA.setStyle(Paint.Style.FILL);\n\n        mForegroundRectFA = new RectF();\n        //tipA\n        mTipPaintA = new Paint(Paint.ANTI_ALIAS_FLAG);\n        mTipPaintA.setStyle(Paint.Style.STROKE);\n        mTipPaintA.setColor(mDoubleThumb.mThumbA.mForeground);\n        mTipPaintA.setTextSize(sp2px(17));\n\n\n        /**\n         * thumbB相关设置\n         */\n        DoubleTumb.Thumb thumbB = mDoubleThumb.mThumbB;\n        if (thumbB != null) {\n            mForegroundPaintB = new Paint(Paint.ANTI_ALIAS_FLAG);\n            mForegroundPaintB.setColor(thumbB.mForeground);\n\n            Drawable foregroundDrawableB = thumbB.mForegroundDrawable;\n            if (foregroundDrawableB != null) {\n                //            mForegroundPaintA.\n                // TODO: 03/12/2018\n            } else {\n                mForegroundPaintB.setColor(thumbB.mForeground);\n            }\n\n            mForegroundPaintB.setStyle(Paint.Style.FILL);\n            mForegroundRectFB = new RectF();\n            //tipB\n            mTipPaintB = new Paint(Paint.ANTI_ALIAS_FLAG);\n            mTipPaintB.setStyle(Paint.Style.STROKE);\n            mTipPaintB.setColor(mDoubleThumb.mThumbB.mForeground);\n            mTipPaintB.setTextSize(sp2px(17));\n        }\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n\n\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n        if (mDoubleThumb == null) {\n            throw new IllegalArgumentException(\"请初始化init()\");\n        }\n        drawBg(canvas);\n        //绘制前景图\n        drawForegroundThumbA(canvas);\n        drawForegroundThumbB(canvas);\n\n        //绘制thumb\n        drawThumbA(canvas);\n        drawThumbB(canvas);\n    }\n\n    @Override\n    public boolean onTouchEvent(MotionEvent event) {\n        float x = event.getX();\n        float y = event.getY();\n        DoubleTumb.Thumb mThumbA = mDoubleThumb.mThumbA;\n        DoubleTumb.Thumb mThumbB = mDoubleThumb.mThumbB;\n        switch (event.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                if (mDisallowIntercept) getParent().requestDisallowInterceptTouchEvent(true);\n                /**\n                 * 判断当前手指是否在触摸thumbA和thumb(存在时)。如果thumbA和thumbB同时存在，优先thumbA为主，且只能触摸一个。\n                 */\n                boolean touchThumbA = mThumbA.isTouchThumb(getContext(), x, y);\n                mThumbA.mTouch = touchThumbA;\n                if (!touchThumbA) {\n                    if (mThumbB != null) {\n                        mThumbB.mTouch = mThumbB.isTouchThumb(getContext(), x, y);\n                        Log.d(TAG, \"onTouchEvent: \" + Arrays.toString(mThumbA.getmTumbPosArr()) + \",\" + x + \",\" + y + \",\" + mThumbA.mTouch);\n                    }\n                } else {\n                    if (mThumbB != null) {\n                        mThumbB.mTouch = false;\n                    }\n                }\n                break;\n            case MotionEvent.ACTION_MOVE:\n                if (mDisallowIntercept) getParent().requestDisallowInterceptTouchEvent(true);\n                if (mThumbA.mTouch) {\n                    //注意左右方向\n                    float len = (mPostionArr[2] - mPostionArr[0]);\n                    float part = mThumbA.mFromLeft ? (x - mPostionArr[0]) : -(x - mPostionArr[2]);\n                    mThumbA.progress = part / len;\n                    if (mThumbA.progress <= 0) {\n                        mThumbA.progress = 0;\n                    }\n                    if (mThumbA.progress >= 1) {\n                        mThumbA.progress = 1;\n                    }\n                    if (mOnDoubleThumbChangeListener != null) {\n                        mOnDoubleThumbChangeListener.onProgressChanged(this, mThumbA.progress, true, true);\n                    }\n\n                    //刷新\n                    invalidate();\n\n                } else if (mThumbB != null && mThumbB.mTouch) {\n                    //注意左右方向\n                    float len = (mPostionArr[2] - mPostionArr[0]);\n                    float part = mThumbB.mFromLeft ? (x - mPostionArr[0]) : -(x - mPostionArr[2]);\n                    mThumbB.progress = part / len;\n                    if (mThumbB.progress <= 0) {\n                        mThumbB.progress = 0;\n                    }\n                    if (mThumbB.progress >= 1) {\n                        mThumbB.progress = 1;\n                    }\n                    if (mOnDoubleThumbChangeListener != null) {\n                        mOnDoubleThumbChangeListener.onProgressChanged(this, mThumbB.progress, false, true);\n                    }\n\n                    //刷新\n                    invalidate();\n                } else {\n\n                }\n                break;\n            case MotionEvent.ACTION_UP:\n                if (mDisallowIntercept)\n                    getParent().requestDisallowInterceptTouchEvent(false);\n                mThumbA.mTouch = false;\n                if (mThumbB != null) mThumbB.mTouch = false;\n                break;\n            default:\n                break;\n        }\n\n        return true;\n    }\n\n    private void drawForegroundThumbB(Canvas canvas) {\n        if (mDoubleThumb.mThumbB == null) return;\n\n        DoubleTumb.Thumb mLeftThumb = mDoubleThumb.mThumbB;\n        boolean mFromLeft = mLeftThumb.mFromLeft;\n        double progress = mLeftThumb.progress;\n        int[] ints = getmPostionArr();\n        float l = mFromLeft ? ints[0] : ints[0] + (float) ((ints[2] - ints[0]) * (1 - progress));\n        float t = ints[1];\n        float r = mFromLeft ? ints[0] + (float) ((ints[2] - ints[0]) * progress) : ints[2];\n        float b = ints[3];\n\n        Log.d(TAG, \"drawForegroundThumbA: \" + progress);\n        //绘制背景\n        mForegroundRectFB.set(l, t, r, b);\n        canvas.drawRoundRect(mForegroundRectFB, mDoubleThumb.mCorners, mDoubleThumb.mCorners, mForegroundPaintB);\n    }\n\n    private void drawThumbB(Canvas canvas) {\n        if (mDoubleThumb.mThumbB == null) return;\n\n        DoubleTumb.Thumb mThumbB = mDoubleThumb.mThumbB;\n        boolean mFromLeft = mThumbB.mFromLeft;\n        double progress = mThumbB.progress;\n        int[] ints = getmPostionArr();\n        float l = mFromLeft ? ints[0] : ints[0] + (float) ((ints[2] - ints[0]) * (1 - progress));\n        float t = ints[1];\n        float r = mFromLeft ? ints[0] + (float) ((ints[2] - ints[0]) * progress) : ints[2];\n        float b = ints[3];\n\n        //开始绘制thumb\n        Bitmap thumbA = getThumbB();\n        float[] tumbPosArr = mThumbB.getmTumbPosArr();\n        tumbPosArr[0] = mFromLeft ? r - mThumbB.getmThumbWidth() / 2.0f : l - mThumbB.getmThumbWidth() / 2.0f;\n        tumbPosArr[1] = t - dp2px(10);\n        tumbPosArr[2] = tumbPosArr[0] + mThumbB.getmThumbWidth() / 2.0f;\n        tumbPosArr[3] = ints[1] + mThumbB.getmThumbHight();\n        canvas.drawBitmap(thumbA, tumbPosArr[0], tumbPosArr[1], mForegroundPaintB);\n\n\n        //绘制tips\n        if (mThumbB.mShowTips) {\n            double len = mDoubleThumb.mMax - mDoubleThumb.mMin;\n\n            /**\n             * 从左边开始计算最小值还是最右边和前景图无关，由开发者手动设置\n             */\n            double realProcess = 0;\n            if (mThumbB.mFromLeft) {\n                if (mDoubleThumb.mMinLeft) {\n                    realProcess = progress;\n                } else {\n                    realProcess = (1 - progress);\n                }\n            } else {\n                if (mDoubleThumb.mMinLeft) {\n                    realProcess = (1 - progress);\n                } else {\n                    realProcess = progress;\n                }\n            }\n\n            double result = mDoubleThumb.mMin + len * realProcess;\n            String format = \"%.\" + mDoubleThumb.mDigit + \"f\";\n            String showTipStr = String.format(format, result);\n            float txtWidth = mTipPaintB.measureText(showTipStr);\n            float x = (tumbPosArr[0] + tumbPosArr[2]) / 2.0f - txtWidth / 2.0f;\n            float y = tumbPosArr[1] - getTipsTopOffset();\n\n            //边界处理\n            if (x < ints[0]) {\n                x = ints[0];\n            }\n            if (x > ints[2] - txtWidth) {\n                x = ints[2] - txtWidth;\n            }\n\n            canvas.drawText(showTipStr, x, y, mTipPaintB);\n        }\n    }\n\n    /**\n     * tips向上的偏移量\n     *\n     * @return\n     */\n    private int getTipsTopOffset() {\n        return dp2px(6);\n    }\n\n    /**\n     * 绘制thumbA前景图,左滑动和右滑动放在了一起，注意三元运算符，\n     *\n     * @param canvas\n     */\n    private void drawForegroundThumbA(Canvas canvas) {\n        DoubleTumb.Thumb mLeftThumb = mDoubleThumb.mThumbA;\n        boolean mFromLeft = mLeftThumb.mFromLeft;\n        double progress = mLeftThumb.progress;\n        int[] ints = getmPostionArr();\n        float l = mFromLeft ? ints[0] : ints[0] + (float) ((ints[2] - ints[0]) * (1 - progress));\n        float t = ints[1];\n        float r = mFromLeft ? ints[0] + (float) ((ints[2] - ints[0]) * progress) : ints[2];\n        float b = ints[3];\n\n        Log.d(TAG, \"drawForegroundThumbA: \" + progress);\n        //绘制背景\n        mForegroundRectFA.set(l, t, r, b);\n        canvas.drawRoundRect(mForegroundRectFA, mDoubleThumb.mCorners, mDoubleThumb.mCorners, mForegroundPaintA);\n    }\n\n    private void drawThumbA(Canvas canvas) {\n        DoubleTumb.Thumb mThumbA = mDoubleThumb.mThumbA;\n        boolean mFromLeft = mThumbA.mFromLeft;\n        double progress = mThumbA.progress;\n        //seekbar四个顶点\n        int[] ints = getmPostionArr();\n        float l = mFromLeft ? ints[0] : ints[0] + (float) ((ints[2] - ints[0]) * (1 - progress));\n        float t = ints[1];\n        float r = mFromLeft ? ints[0] + (float) ((ints[2] - ints[0]) * progress) : ints[2];\n        float b = ints[3];\n\n        //开始绘制thumb\n        Bitmap thumbA = getThumbA();\n        float[] tumbPosArr = mThumbA.getmTumbPosArr();\n        tumbPosArr[0] = mFromLeft ? r - mThumbA.getmThumbWidth() / 2.0f : l - mThumbA.getmThumbWidth() / 2.0f;\n        tumbPosArr[1] = t - dp2px(10);\n        tumbPosArr[2] = tumbPosArr[0] + mThumbA.getmThumbWidth() / 2.0f;\n        tumbPosArr[3] = ints[1] + mThumbA.getmThumbHight();\n        canvas.drawBitmap(thumbA, tumbPosArr[0], tumbPosArr[1], mForegroundPaintA);\n\n        //绘制tips\n        if (mThumbA.mShowTips) {\n            double len = mDoubleThumb.mMax - mDoubleThumb.mMin;\n\n            /**\n             * 从左边开始计算最小值还是最右边和前景图无关，由开发者手动设置\n             */\n            double realProcess = 0;\n            if (mThumbA.mFromLeft) {\n                if (mDoubleThumb.mMinLeft) {\n                    realProcess = progress;\n                } else {\n                    realProcess = (1 - progress);\n                }\n            } else {\n                if (mDoubleThumb.mMinLeft) {\n                    realProcess = (1 - progress);\n                } else {\n                    realProcess = progress;\n                }\n            }\n\n            double result = mDoubleThumb.mMin + len * realProcess;\n            String format = \"%.\" + mDoubleThumb.mDigit + \"f\";\n            String showTipStr = String.format(format, result);\n            float txtWidth = mTipPaintA.measureText(showTipStr);\n            float x = (tumbPosArr[0] + tumbPosArr[2]) / 2.0f - txtWidth / 2.0f;\n            float y = tumbPosArr[1] - getTipsTopOffset();\n\n            //边界处理\n            if (x < ints[0]) {\n                x = ints[0];\n            }\n            if (x > ints[2] - txtWidth) {\n                x = ints[2] - txtWidth;\n            }\n\n            canvas.drawText(showTipStr, x, y, mTipPaintA);\n        }\n\n    }\n\n    private void drawBg(Canvas canvas) {\n        int[] ints = getmPostionArr();\n        mBackgroudRectF.set(ints[0], ints[1], ints[2], ints[3]);\n        canvas.drawRoundRect(mBackgroudRectF, mDoubleThumb.mCorners, mDoubleThumb.mCorners, mBackgroudPaint);\n    }\n\n    /**\n     * 获取进度条四个角的位置坐标\n     *\n     * @return\n     */\n    private int[] getmPostionArr() {\n        if (mPostionArr == null) {\n            mPostionArr = new int[4];\n            mPostionArr[0] = 0 + mDoubleThumb.mLineLeft;\n            mPostionArr[1] = 0 + mDoubleThumb.mLineTop;\n            mPostionArr[2] = getWidth() - mDoubleThumb.mLineRight;\n            mPostionArr[3] = getHeight() - mDoubleThumb.mLineBottom;\n        }\n        return mPostionArr;\n    }\n\n    public boolean isDisallowIntercept() {\n        return mDisallowIntercept;\n    }\n\n    public DoubleThumbSeekBar setDisallowIntercept(boolean disallowIntercept) {\n        mDisallowIntercept = disallowIntercept;\n        return this;\n    }\n\n    /**\n     * 获取thumbA\n     *\n     * @return\n     */\n    @NonNull\n    private Bitmap getThumbA() {\n        if (mThumbBitmapA == null) {\n            DoubleTumb.Thumb mThumbA = mDoubleThumb.mThumbA;\n            Drawable drawable = mThumbA.getmThumb();\n            if (drawable == null) {\n                throw new IllegalArgumentException(\"请提供mThumbA的Drawable\");\n            }\n            mThumbBitmapA = RenderUtils.drawableToBitmap(drawable, mThumbA.getmThumbWidth(), mThumbA.getmThumbHight());\n        }\n        return mThumbBitmapA;\n    }\n\n    /**\n     * 获取thumbB\n     *\n     * @return\n     */\n    @NonNull\n    private Bitmap getThumbB() {\n        if (mDoubleThumb.mThumbB == null) {\n            throw new IllegalArgumentException(\"请先初始化ThumbB\");\n        }\n\n        if (mThumbBitmapB == null) {\n            Drawable drawable = null;\n            DoubleTumb.Thumb mThumbB = mDoubleThumb.mThumbB;\n            drawable = mThumbB.getmThumb();\n            if (drawable == null) {\n                throw new IllegalArgumentException(\"请提供mThumbB的Drawable\");\n            }\n            mThumbBitmapB = RenderUtils.drawableToBitmap(drawable, mThumbB.getmThumbWidth(), mThumbB.getmThumbHight());\n        }\n        return mThumbBitmapB;\n    }\n\n    public interface OnDoubleThumbChangeListener {\n        /**\n         * 监听滑动\n         *\n         * @param seekBar  当前seekbar对象\n         * @param progress 进度百分比，[0,1]\n         * @param thumbA   是否是thumbA,true:thumbA,false:thumbB。同时只允许滑动一个进度thumb.\n         * @param fromUser 是否是用户自己手动触发的\n         */\n        void onProgressChanged(DoubleThumbSeekBar seekBar, double progress, boolean thumbA, boolean fromUser);\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/java/com/tophold/trade/view/seekbar/DoubleTumb.java",
    "content": "package com.tophold.trade.view.seekbar;\n\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\nimport android.support.annotation.ColorInt;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\n\n/**\n * ============================================================\n * 作 者 :    wgyscsf@163.com\n * 更新时间 ：2018/11/30 14:13\n * 描 述 ：\n * ============================================================\n */\npublic class DoubleTumb {\n    public double mMin;\n    public double mMax;\n    public float mCorners;\n    @ColorInt\n    public int mBackground;\n    @NonNull\n    public Thumb mThumbA;\n    @Nullable\n    public Thumb mThumbB;//是否启用双thumb以这个参数为空不为空所解决。当这个不为空则显示双thumb.\n    public int mDigit = 4;//精度\n    //最小值从左边开始还是从右边开始,和前景图无关\n    public boolean mMinLeft = true;\n\n    /**\n     * 内部属性\n     */\n    //背景的四边内间距\n    public int mLineTop, mLineBottom, mLineLeft, mLineRight;\n\n\n    public DoubleTumb(double mMin, double mMax, float mCorners,\n                      @ColorInt int mBackground,\n                      @NonNull Thumb mThumbA,\n                      @Nullable Thumb mThumbB) {\n        this.mMin = mMin;\n        this.mMax = mMax;\n        this.mCorners = mCorners;\n        this.mBackground = mBackground;\n        this.mThumbA = mThumbA;\n        this.mThumbB = mThumbB;\n    }\n\n\n    public static class Thumb {\n        public boolean mFromLeft = true;\n        @ColorInt\n        public int mForeground;\n        public Drawable mForegroundDrawable;\n\n        //进度，确认当前thumb所在的位置，值为百分比\n        public double progress;\n        //thumb\n        private Drawable mThumb;\n        private int mThumbWidth;\n        private int mThumbHight;\n        //是否展示当前htumb的值\n        public boolean mShowTips;\n\n        /**\n         * 内部使用属性\n         */\n        //thumb的位置坐标，四个点的,用于判断手指是否在按压范围内。左、上、右、下\n        private float[] mTumbPosArr = new float[4];\n        //是否正在按压\n        public boolean mTouch = false;\n\n        public int getmThumbWidth() {\n            if (mThumbWidth <= 0) {\n                if (mThumb != null)\n                    return mThumb.getIntrinsicWidth();\n            }\n            return mThumbWidth;\n        }\n\n        public Thumb setmThumbWidth(int mThumbWidth) {\n            this.mThumbWidth = mThumbWidth;\n            return this;\n        }\n\n        public int getmThumbHight() {\n            if (mThumbHight <= 0) {\n                if (mThumb != null)\n                    return mThumb.getIntrinsicHeight();\n            }\n            return mThumbHight;\n        }\n\n        public Thumb setmThumbHight(int mThumbHight) {\n            this.mThumbHight = mThumbHight;\n            return this;\n        }\n\n        public Thumb(int mForeground) {\n            this.mForeground = mForeground;\n        }\n\n        public Thumb(boolean mFromLeft, Drawable mForegroundDrawable) {\n            this.mFromLeft = mFromLeft;\n            this.mForegroundDrawable = mForegroundDrawable;\n        }\n\n        public Drawable getmThumb() {\n            return mThumb;\n        }\n\n        public Thumb setmThumb(Drawable mThumb) {\n            this.mThumb = mThumb;\n            return this;\n        }\n\n        public float[] getmTumbPosArr() {\n            return mTumbPosArr;\n        }\n\n        /**\n         * 传递的x、y是否在按压范围内\n         *\n         * @param context\n         * @param x\n         * @param y\n         * @return\n         */\n        public boolean isTouchThumb(Context context, float x, float y) {\n            float touchOffset = getTouchOffset(context);\n            float[] ints = getmTumbPosArr();\n            ints[0] -= touchOffset;\n            ints[1] -= touchOffset;\n            ints[2] += touchOffset;\n            ints[3] += touchOffset;\n            return x >= ints[0] && x <= ints[2] && y >= ints[1] && y <= ints[3];\n        }\n\n        /**\n         * 扩大按压区域\n         *\n         * @param context\n         * @return\n         */\n        public float getTouchOffset(Context context) {\n            final float scale = context.getResources().getDisplayMetrics().density;\n            return (int) (2 * scale + 0.5f);\n        }\n    }\n}\n"
  },
  {
    "path": "financiallib/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n\n    <!--++++++++++++++++++基金收益自定义View++++++++++++++++++++-->\n    <!--基金自定义view相关属性-->\n    <color name=\"color_fundView_xyTxtColor\">#787274</color>\n    <color name=\"color_fundView_xLineColor\">#c1bdbe</color>\n    <color name=\"color_fundView_brokenLineColor\">#3785d9</color>\n    <color name=\"color_fundView_longPressLineColor\">#ec210f</color>\n    <color name=\"color_fundView_pressIncomeTxt\">#ec210f</color>\n    <color name=\"color_fundView_pressIncomeTxtBg\">#87c9e7</color>\n    <color name=\"color_fundView_defIncomeTxt\">#000000</color>\n\n\n    <!--++++++++++++++++++++KView相关，包括：分时图、副图  开始+++++++++++++++++++++++++++++++++++++++++++++++-->\n\n    <!--公共属性-->\n    <!--外边框颜色-->\n    <color name=\"color_kview_outerStrokeColor\">#787274</color>\n    <color name=\"color_kview_loadingTxtColor\">#787274</color>\n    <!--内部xy虚线-->\n    <color name=\"color_kview_innerXyDashColor\">#787274</color>\n\n\n    <!--++++++++++++++++++分时图自定义View++++++++++++++++++++-->\n    <!--分时图相关属性-->\n    <!--折线图-->\n    <color name=\"color_timeSharing_brokenLineColor\">#3785d9</color>\n    <!--折线图最后的小圆点的颜色-->\n    <color name=\"color_timeSharing_dotColor\">#3785d9</color>\n    <!--实时横线颜色-->\n    <color name=\"color_timeSharing_timingLineColor\">#ec210f</color>\n    <!--折线下面的浅蓝色-->\n    <color name=\"color_timeSharing_blowBlueColor\">#74caf9</color>\n    <!--x、y轴文字的颜色-->\n    <color name=\"color_timeSharing_xYTxtColor\">#787274</color>\n    <!--实时横线右侧的红色的框和实时数据颜色-->\n    <color name=\"color_timeSharing_timingTxtColor\">#ffffff</color>\n    <color name=\"color_timeSharing_timingTxtBgColor\">#ec210f</color>\n    <!--长按十字线的颜色-->\n    <color name=\"color_timeSharing_longPressLineColor\">#7b797b</color>\n    <!--长按十字时间、数据的框和文字颜色-->\n    <color name=\"color_timeSharing_longPressTxtColor\">#ffffff</color>\n    <color name=\"color_timeSharing_longPressTxtBgColor\">#7b797b</color>\n    <!--回调的颜色-->\n    <color name=\"color_timeSharing_callBackRed\">#ec210f</color>\n    <color name=\"color_timeSharing_callBackGreen\">#12ec3a</color>\n\n    <!--蜡烛图的颜色-->\n    <color name=\"color_timeSharing_candleRed\">#ec210f</color>\n    <color name=\"color_timeSharing_candleGreen\">#12ec3a</color>\n    <color name=\"color_timeSharing_candleEqual\">#5d5dec</color>\n\n    <!--主图指标-->\n    <color name=\"color_masterView_legendColor\">#8f8a8a</color>\n\n\n    <!--MA-->\n    <color name=\"color_masterView_ma5Color\">#dcb1ad</color>\n    <color name=\"color_masterView_ma10Color\">#72a5e4</color>\n    <color name=\"color_masterView_ma20Color\">#3785d9</color>\n\n    <!--boll-->\n    <color name=\"color_masterView_bollUpColor\">#ed978f</color>\n    <color name=\"color_masterView_bollMbColor\">#136ad6</color>\n    <color name=\"color_masterView_bollDnColor\">#7897b9</color>\n\n    <color name=\"color_minmax\">#f23f09</color>\n\n    <!--++++++++++++++++++副图自定义View++++++++++++++++++++-->\n\n    <!--共有属性-->\n    <!--外边框颜色-->\n    <color name=\"color_minorView_outerStrokeColor\">#787274</color>\n    <!--内部xy虚线-->\n    <color name=\"color_minorView_innerXyDashColor\">#787274</color>\n    <!--x、y轴文字的颜色-->\n    <color name=\"color_minorView_xYTxtColor\">#787274</color>\n    <!--图例文字的颜色-->\n    <color name=\"color_minorView_legendTxtColor\">#787274</color>\n    <!--长按十字时间、数据的框和文字颜色-->\n    <color name=\"color_minorView_longPressTxtColor\">#ffffff</color>\n\n    <!--macd相关-->\n    <color name=\"color_minorView_macdBuyColor\">#ec210f</color>\n    <color name=\"color_minorView_macdSellColor\">#5aab52</color>\n    <color name=\"color_minorView_macdDifColor\">#dcb1ad</color>\n    <color name=\"color_minorView_macdDeaColor\">#9941e1</color>\n    <color name=\"color_minorView_macdMacdColor\">#3785d9</color>\n\n    <!--rsi相关-->\n    <color name=\"color_minorView_rsi6Color\">#dcb1ad</color>\n    <color name=\"color_minorView_rsi12Color\">#9941e1</color>\n    <color name=\"color_minorView_rsi24Color\">#3785d9</color>\n\n    <!--kdj相关-->\n    <color name=\"color_minorView_kColor\">#dcb1ad</color>\n    <color name=\"color_minorView_dColor\">#9941e1</color>\n    <color name=\"color_minorView_jColor\">#3785d9</color>\n\n    <!--++++++++++++++++++++KView相关，包括：分时图、副图  结束+++++++++++++++++++++++++++++++++++++++++++++++-->\n\n\n    <!--饼图-->\n    <color name=\"color_pie_chart_red\">#ef1e13</color>\n    <color name=\"color_pie_chart_gray\">#8a8a8b</color>\n\n\n    <!--具体业务-->\n    <color name=\"color_tb_indicator\">#ef1e13</color>\n    <color name=\"color_tb_selectedTxt\">#ef1e13</color>\n    <color name=\"color_tb_Txt\">#8a8a8b</color>\n\n</resources>\n"
  },
  {
    "path": "financiallib/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">FinancialCustomerView</string>\n    <string name=\"string_fundView_defHintTxt\">累计收益:</string>\n    <string name=\"string_fundView_pressHintTxt\">累计盈亏:</string>\n    <string name=\"string_placeHold\">--</string>\n\n    <!-- TODO: Remove or change this placeholder text -->\n    <string name=\"hello_blank_fragment\">Hello blank fragment</string>\n</resources>\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n\n##release\nrelease_storeFile=../key/financial.jks\nrelease_storePassword=wgyscsf\nrelease_keyAlias=wgyscsf\nrelease_keyPassword=wgyscsf\n##debug\ndebug_storeFile=../key/financial.jks\ndebug_storePassword=wgyscsf\ndebug_keyAlias=wgyscsf\ndebug_keyPassword=wgyscsf"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app', ':financiallib'\n"
  },
  {
    "path": "资料与文档/效果图和进度.md",
    "content": "## 金融类自定义view\n\n#### FundView.view\n\n> 仿蚂蚁金服基金收益趋势图\n\n* 贡献代码\n\n    新建分支\n\n* v1.0 完成x轴日期提示文字、y轴收益提示文字、x轴虚线、折线图\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/v1.0_img1.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/v1.0_img1.png?raw=true)\n\n* v1.1 完成长按显示距离按下焦点最近的日期以及对应收益点十字、默认上方提示收益、按下上方显示对应点的时间和累计收益、延迟消失十字效果（仿蚂蚁金融）\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/v1.1_img_nopress.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/v1.1_img_nopress.png?raw=true)\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/v1.1_img_press.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/v1.1_img_press.png?raw=true)\n\n#### TimeSharingView.view\n\n> 股票、外汇等交易类的分时图。版本已稳定。\n\n* 贡献代码\n\n    提交到[timesharing]分支\n\n* 第一阶段，参数准备，外边框、内虚线、折线图等的绘制\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2.png?raw=true)\n\n* 第二阶段，x、y文字、实时横线和实时数据、下方透明阴影\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2_%E5%AE%8C%E5%96%84.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2_%E5%AE%8C%E5%96%84.png)\n\n* 第三阶段，实时数据更新分时图\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E5%AE%9E%E6%97%B6%E6%95%B0%E6%8D%AE%E6%98%BE%E7%A4%BA.gif](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E5%AE%9E%E6%97%B6%E6%95%B0%E6%8D%AE%E6%98%BE%E7%A4%BA.gif)\n\n* 第四阶段，长按十字线，左右移动分时图\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E5%8F%AF%E4%BB%A5%E9%95%BF%E6%8C%89_%E5%8F%AF%E4%BB%A5%E5%B7%A6%E5%8F%B3%E6%8B%96%E5%8A%A8.gif?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E5%8F%AF%E4%BB%A5%E9%95%BF%E6%8C%89_%E5%8F%AF%E4%BB%A5%E5%B7%A6%E5%8F%B3%E6%8B%96%E5%8A%A8.gif?raw=true)\n\n* 第五阶段，长按实时显示详细数据、加载更多处理、实时横线优化、滑动优化\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/dev/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%BA%94%E9%98%B6%E6%AE%B5_%E5%8A%A0%E8%BD%BD%E6%9B%B4%E5%A4%9A.gif](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/dev/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%BA%94%E9%98%B6%E6%AE%B5_%E5%8A%A0%E8%BD%BD%E6%9B%B4%E5%A4%9A.gif)\n\n* 第六阶段，缩放、代码整理、注释\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E5%85%AD%E9%98%B6%E6%AE%B5_%E7%BC%A9%E6%94%BE-%E4%BB%A3%E7%A0%81%E4%BC%98%E5%8C%96-%E6%B3%A8%E9%87%8A.gif?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E5%85%AD%E9%98%B6%E6%AE%B5_%E7%BC%A9%E6%94%BE-%E4%BB%A3%E7%A0%81%E4%BC%98%E5%8C%96-%E6%B3%A8%E9%87%8A.gif?raw=true)\n\n\n#### CanldeView.view\n\n> 股票、外汇等交易类的蜡烛图。版本不稳定，正在完善中，相关代码在'feature_candleview'分支\n\n* 贡献代码\n\n    提交到[feature_candleview]分支\n\n* 第一阶段，代码的大量重构，抽出父类，减少子类代码量。代码优化，减少for循环层次。\n* 第二阶段，完成MA、BOLL相关算法。\n* 第三阶段，完成蜡烛图。\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E8%9C%A1%E7%83%9B%E5%9B%BE.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E8%9C%A1%E7%83%9B%E5%9B%BE.png)\n\n\n* 第四阶段，MA指标图、BOLL指标图、蜡烛图长按处理\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_ma_nopress.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_ma_nopress.png)\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_ma_press.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_ma_press.png)\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_gif.gif](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_gif.gif)\n\n#### KView.view\n \n> 主图和副图的组合图已经开发完毕，可以下载demo apk体验：[https://github.com/scsfwgy/FinancialCustomerView/tree/master/apk](https://github.com/scsfwgy/FinancialCustomerView/tree/master/apk)\n效果视频：[https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/%E4%B8%BB%E5%9B%BE%E5%89%AF%E5%9B%BE%E7%BB%84%E5%90%88%E5%9B%BEdemo%E8%A7%86%E9%A2%91.mp4](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/%E4%B8%BB%E5%9B%BE%E5%89%AF%E5%9B%BE%E7%BB%84%E5%90%88%E5%9B%BEdemo%E8%A7%86%E9%A2%91.mp4)"
  },
  {
    "path": "资料与文档/整理的指标算法.md",
    "content": "# 整理算法\n## 简称和命名\n### Quotes\n* 最原始的Quote对象包含五个字段：t,o,c,l,h\n    * t 时间，该报价单元生成的时间戳\n    * o 开盘价，该报价单元的开始报价\n    * c 闭盘价，该报价单元的结束报价\n    * l 最低价，该报价单元的最低价\n    * h 最高价，该报价单元的最高价\n\n## 算法和示例代码\n### MA\n> 移动平均线，Moving Average，简称MA，MA是用统计分析的方法，将一定时期内的证券价格（指数）加以平均，并把不同时间的平均值连接起来，形成一根MA，用以观察证券价格变动趋势的一种技术指标。[[百度百科：移动平均线](https://baike.baidu.com/item/%E7%A7%BB%E5%8A%A8%E5%B9%B3%E5%9D%87%E7%BA%BF/217887?fr=aladdin&fromid=1511750&fromtitle=MA)]\n\n#### MA算法\n* MA5,指的是5单位的移动平均线，其它同理。MA(5,10,20)指的是5单位、10单位、20单位三条移动平均线。\n* 很多资料都把MAn,称为n天的移动平均线，感觉这样是不合理的，因为折线图有很多类型，比如1分钟的、1小时的、1周的等等。所以，这里\"n\"不应该称为“天”，而是应该是对应的类型，所以这里直接称为“单位”。\n* 计算公式：MA =(C1+C2+C3+C4+C5+...+Cn)/n,其中C为收盘价n为移动平均周期数。例如现货黄金的5日移动平均价格计算方法为：MA5=(前四天收盘价+前三天收盘价+前天收盘价+昨天收盘价+今天收盘价)/5。\n* 指定点的MAn值的计算，就是从该点开始(包括该点)起向历史数据取n个数据单元的收盘价之和，然后取均值。\n* 特殊的，假如数据集合中最开始的n个数据，是没法计算MAn的。这里的处理方式有两种\n    1. 对于最开始的n个点，直接用当日的收盘价当作对应MA值即可。\n    2. 不计算，绘制时直接不绘制对应MA即可。本项目采用这种方式。\n\n#### MA示例代码\n* 本项目中处理MA只计算MA5,MA10，MA20。并且直接在Quotes中定义该三个字段，计算好之后直接赋值。\n* 示例代码\n\n```java\n   /**\n     * 计算公式：MA =(C1+C2+C3+C4+C5+...+Cn)/n,其中C为收盘价n为移动平均周期数。\n     * 例如现货黄金的5日移动平均价格计算方法为：MA5=(前四天收盘价+前三天收盘价+前天收盘价+昨天收盘价+今天收盘价)/5。\n     * 特殊的，假如数据集合中最开始的n个数据，是没法计算MAn的。这里的处理方式是不计算，绘制时直接不绘制对应MA即可。\n     * @param quotesList 数据集合\n     * @param period MAn中的n\n     */\n    public static void calculateMA(List<Quotes> quotesList, int period) {\n\n        if (quotesList == null || quotesList.isEmpty()) return;\n\n        if (period < 0 || period > quotesList.size() - 1) return;\n\n        double sum = 0;\n        for (int i = 0; i < quotesList.size(); i++) {\n            //计算和\n            Quotes quotes = quotesList.get(i);\n            sum += quotes.c;\n            if (i > period - 1) {\n                sum -= quotesList.get(i - period).c;\n            }\n\n            //边界\n            if (i < period - 1) {\n                continue;\n            }\n\n            if (period == 5) {\n                quotes.ma5 = sum / period;\n            } else if (period == 10) {\n                quotes.ma10 = sum / period;\n            } else if (period == 20) {\n                quotes.ma20 = sum / period;\n            } else {\n                Log.e(TAG, \"calculateMA: 没有该种period，TODO:完善Quotes\");\n                return;\n            }\n\n        }\n    }\n```\n\n### BOLL\n> 布林线,Boll,是股市技术分析的常用工具之一，通过计算股价的“标准差”，再求股价的“信赖区间”。该指标在图形上画出三条线，其中上下两条线可以分别看成是股价的压力线和支撑线，而在两条线之间还有一条股价平均线，布林线指标的参数最好设为20。一般来说，股价会运行在压力线和支撑线所形成的通道中。[[百度百科：布林线](https://baike.baidu.com/item/%E5%B8%83%E6%9E%97%E7%BA%BF/3424486?fr=aladdin)]\n\n#### BOLL算法\n* BOLL(n),指的是n单位的BOLL线。\n* BOLL(n)包含三条线，中轨线（MB）、上轨线（UP）和下轨线（DN）。\n* BOLL(n)计算公式：\n    * MA=n日内的收盘价之和÷n。\n    * MD=（n-1）日的平方根（C－MA）的两次方之和除以n\n    * MB=（n－1）日的MA\n    * UP=MB+k×MD\n    * DN=MB－k×MD\n    * K为参数，可根据股票的特性来做相应的调整，一般默认为2\n* 特殊的，假如数据集合中最开始的n个数据，是没法计算BOLL(n)的。这里的处理方式有两种\n    1. 对于最开始的n个点，直接用当日的收盘价当作当日的MA值即可。\n    2. 不计算，绘制时直接不绘制对应BOLL即可。本项目采用这种方式。\n\n#### BOLL示例代码\n* 本项目中处理MA只计算BOLL(26),k=2。并且直接在Quotes中定义mb、up、dn，计算好之后直接赋值。\n* 示例代码\n\n```java\n    /**\n     * BOLL(n)计算公式：\n     * MA=n日内的收盘价之和÷n。\n     * MD=（n-1）日的平方根（C－MA）的两次方之和除以n\n     * MB=（n－1）日的MA\n     * UP=MB+k×MD\n     * DN=MB－k×MD\n     * K为参数，可根据股票的特性来做相应的调整，一般默认为2\n     *\n     * @param quotesList 数据集合\n     * @param period 周期，一般为26\n     * @param k 参数，可根据股票的特性来做相应的调整，一般默认为2\n     */\n    public static void calculateBOLL(List<Quotes> quotesList, int period, int k) {\n        if (quotesList == null || quotesList.isEmpty()) return;\n        if (period < 0 || period > quotesList.size() - 1) return;\n\n        double mb;//上轨线\n        double up;//中轨线\n        double dn;//下轨线\n\n        //n日\n        double sum = 0;\n        //n-1日\n        double sum2=0;\n        for (int i = 0; i < quotesList.size(); i++) {\n            Quotes quotes = quotesList.get(i);\n            sum += quotes.c;\n            sum2+=quotes.c;\n            if (i > period - 1)\n                sum -= quotesList.get(i - period).c;\n            if(i>period-2)\n                sum2 -= quotesList.get(i - period+1).c;\n\n            //这个范围不计算，在View上的反应就是不显示这个范围的boll线\n            if (i < period - 1)\n                continue;\n\n            //n日MA\n            double ma = sum / period;\n            //n-1日MA\n            double ma2=sum2/(period-1);\n            double md = 0;\n            for (int j = i + 1 - period; j <= i; j++) {\n                //n-1日\n                md += Math.pow(quotesList.get(j).c - ma, 2);\n            }\n            md = Math.sqrt(md / period);\n            //(n－1）日的MA\n            mb = ma2;\n            up = mb + k * md;\n            dn = mb - k * md;\n\n            quotes.mb = mb;\n            quotes.up = up;\n            quotes.dn = dn;\n        }\n    }\n\n```\n\n\n\n"
  },
  {
    "path": "资料与文档/金融类自定义View（一）--仿蚂蚁财富基金收益曲线图.md",
    "content": "## 金融类自定义View（一）--仿蚂蚁财富基金收益曲线图\n> 该自定义View模仿了蚂蚁金服的基金收益曲线图走势。大致包含以下功能：x轴绘制等分时间坐标；y轴绘制等分收益值；中间绘制等分虚线；收益变化折线图；上方默认显示最后收益值；长按显示当前距离最近按下点的时间坐标以及对应收益值的十字线，同时上方显示对应时间与收益。看似简单的一个收益曲线图，包含很多细节技术点需要处理。虽然该自定义View比较简单，但是和金融类复杂的K线图、蜡烛图等以及相应复杂的交互本质上是一样的，会提供很好的解决思路。本文不会讲解自定义View入门知识。enjoy it~\n\n#### 效果图\n* 原蚂蚁金服收益View操作GIF\n\n![](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/master/img/ant.gif)\n\n* 仿操作GIF\n\n![](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/master/img/fang.gif)\n\n* 截图\n\n![](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/master/img/ant_nopress.PNG)\n\n![](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/master/img/ant_press.PNG)\n\n![](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/master/img/fang_nopress.png)\n\n![](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/master/img/fang_press.png)\n\n#### 中间虚线的绘制\n* 要绘制横轴那五条虚线，我们首先需要知道该控件的大小和位置，由调用者在使用时设置，控件在onMeasure()的时候获取，特别注意处理一下`AT_MOST`的情况。另外，我们需要设置上下左右的起始位置，也就是给该控件设置好Padding值，如下：\n\n\t\t//上下左右padding\n\t\tfloat mPaddingTop = 100;\n\t\tfloat mPaddingBottom = 70;\n\t\tfloat mPaddingLeft = 50;\n\t\tfloat mPaddingRight = 50;\n\n* 知道了绘制的起始和结束位置之后，我们需要初始化一个绘制虚线的画笔，用来在Canves上绘制虚线\n\n\t\t//初始化绘制虚线的画笔\n\t    private void initInnerXPaint() {\n\t        mInnerXPaint = new Paint();\n\t        mInnerXPaint.setColor(getColor(R.color.color_fundView_xLineColor));\n\t        mInnerXPaint.setStrokeWidth(convertDp2Px(mInnerXStrokeWidth));\n\t        mInnerXPaint.setStyle(Paint.Style.STROKE);\n\t        setLayerType(LAYER_TYPE_SOFTWARE, null);//禁用硬件加速\n\t        PathEffect effects = new DashPathEffect(new float[]{5, 5, 5, 5}, 1);\n\t        mInnerXPaint.setPathEffect(effects);\n\t    }\n\n* 其实知道位置和初始化画笔之后，就可以直接绘制了。我们很容易知道最上面的那一条的起始点和结束点是`(mPaddingLeft, mPaddingTop)`,`(mWidth - mPaddingRight, mPaddingTop)`,就是左右上边界减去左右和上的Padding值。同理，下方的位置也很好确定。至于中间那三条线的确定，因为是上下平移，所以主要是确定y周的坐标。我们可以根据最下面线的y周坐标减去最上面的y轴值取均分值即可：\n\n\t\t private void drawInnerXPaint(Canvas canvas) {\n\t\t        //画5条横轴的虚线\n\t\t        //首先确定最大值和最小值的位置\n\t\t        float perHight = (mHeight - mPaddingBottom - mPaddingTop) / 4;\n\t\t\n\t\t        canvas.drawLine(0 + mPaddingLeft, mPaddingTop,\n\t\t                mWidth - mPaddingRight, mPaddingTop, mInnerXPaint);//最上面的那一条\n\t\t\n\t\t        canvas.drawLine(0 + mPaddingLeft, mPaddingTop + perHight * 1,\n\t\t                mWidth - mPaddingRight, mPaddingTop + perHight * 1, mInnerXPaint);//2\n\t\t\n\t\t        canvas.drawLine(0 + mPaddingLeft, mPaddingTop + perHight * 2,\n\t\t                mWidth - mPaddingRight, mPaddingTop + perHight * 2, mInnerXPaint);//3\n\t\t\n\t\t        canvas.drawLine(0 + mPaddingLeft, mPaddingTop + perHight * 3,\n\t\t                mWidth - mPaddingRight, mPaddingTop + perHight * 3, mInnerXPaint);//4\n\t\t\n\t\t        canvas.drawLine(0 + mPaddingLeft, mHeight - mPaddingBottom,\n\t\t                mWidth - mPaddingRight, mHeight - mPaddingBottom, mInnerXPaint);//最下面的那一条\n\t\t\n\t\t    }\n\n* 按照上述步骤执行完毕之后，`invalidate()`刷新界面即可。其实虚线的绘制还是比较简单的，主要是定位、定分y周轴。\n\n#### x轴时间文字和y轴收益文字的定位和绘制\n* 首先定义绘制x\\y轴文字的画笔、字体大小颜色等属性。当然，如果要细分x轴和y轴可以定义两套Paint,这里简单处理，只用了一个Paint:\n\n\t \t//外围X、Y轴线文字\n\t    Paint mXYPaint;\n\t    //x、y轴指示文字字体的大小\n\t    final float mXYTextSize = 14;\n\t    //左侧文字距离左边线线的距离\n\t    final float mLeftTxtPadding = 16;\n\t    //底部文字距离底部线的距离\n\t    final float mBottomTxtPadding = 20;\n\n* 对于x轴的处理，我们只需要获取列表中第一个Model的时间值、结束位置的时间值和中间值寄存下来，然后在固定位置显示即可。对于第一个时间的位置，和绘制最下面一条虚线定位一样。中间时间文字的显示，x轴的坐标是：总宽度减去左右pading值，然后取半再加上左边pdding值。当然，你如果仔细观察，这个时候x并不是居中显示的，因为是从**中间点**开始显示的，所有会错一个一半的时间文字宽度的值，这个时候应该再减去txt.lnegth()/2。同理，最后一个时间点的x轴开始位置也是需要减去文字的宽度的，不然就会绘制出范围。特别注意，为了好看，我们让文字向下偏移了一定的距离：`float hight = mHeight - mPaddingBottom + mBottomTxtPadding;`。\n\n\t\t  //找到最大时间、最小时间和中间时间显示即可\n\t\t    private void drawXPaint(Canvas canvas) {\n\t\t        long beginTime = mFundModeList.get(0).datetime;\n\t\t        long midTime = mFundModeList.get((mFundModeList.size() - 1) / 2).datetime;\n\t\t        long endTime = mFundModeList.get(mFundModeList.size() - 1).datetime;\n\t\t        String bengin = processDateTime(beginTime);\n\t\t        String mid = processDateTime(midTime);\n\t\t        String end = processDateTime(endTime);\n\t\t\n\t\t        //x轴文字的高度\n\t\t        float hight = mHeight - mPaddingBottom + mBottomTxtPadding;\n\t\t\n\t\t        canvas.drawText(bengin,\n\t\t                mPaddingLeft,\n\t\t                hight, mXYPaint);\n\t\t\n\t\t        canvas.drawText(mid,\n\t\t                mPaddingLeft + (mWidth - mPaddingLeft - mPaddingRight) / 2,\n\t\t                hight, mXYPaint);\n\t\t\n\t\t        canvas.drawText(end,\n\t\t                mWidth - mPaddingRight - mXYPaint.measureText(end),\n\t\t                hight, mXYPaint);//特别注意x轴的处理：- mXYPaint.measureText(end)\n\t\t\n\t\t    }\n\n\n* 对于y轴文字的处理，我们并不知道最小值和最大值，所以我们需要遍历记录下最小值和最大值。然后均分取间距，在左侧绘制即可。也需要特别注意文字绘制起始点的问题。\n\n#### 折线的绘制\n* 对于折线的处理就比较麻烦了。按照上述思路，x轴可以直接取有效总宽度除以数据总个数，计算出每一个点的宽度即可。对于y轴，我们可以考虑一下，y轴的收益可能小到1分，或者大到100元，怎么确定每一点的y轴位置，如何保证绘制的曲线不出有效范围？我们可以用y轴有效的总高度除以收益的最大最小区间，获取每个单位的高度。当绘制时，根据对应时间点的收益乘以单位收益，即可以计算出需要的高度：\n\n\t\t//获取单个数据X/y轴的大小\n        mPerX = (mWidth - mPaddingLeft - mPaddingRight) / mFundModeList.size();\n        mPerY = ((mHeight - mPaddingTop - mPaddingBottom) / (mMaxFundMode.dataY - mMinFundMode.dataY));\n        Log.e(TAG, \"setDataList: \" + mMinFundMode + \",\" + mMaxFundMode + \"...\" + mPerX + \",\" + mPerY);\n\n* 根据上述计算出来单位高度，绘制y轴文字信息\n\n\t\tprivate void drawYPaint(Canvas canvas) {\n\t\t        //现将最小值、最大值画好\n\t\t        //draw min\n\t\t        float txtWigth = mXYPaint.measureText(mMinFundMode.originDataY) + mLeftTxtPadding;\n\t\t        canvas.drawText(mMinFundMode.originDataY + \"\",\n\t\t                mPaddingLeft - txtWigth,\n\t\t                mHeight - mPaddingBottom, mXYPaint);\n\t\t        //draw max\n\t\t        canvas.drawText(mMaxFundMode.dataY + \"\",\n\t\t                mPaddingLeft - txtWigth,\n\t\t                mPaddingTop, mXYPaint);\n\t\t        //因为横线是均分的，所以只要取到最大值最小值的差值，均分即可。\n\t\t        float perYValues = (mMaxFundMode.dataY - mMinFundMode.dataY) / 4;\n\t\t        float perYWidth = (mHeight - mPaddingBottom - mPaddingTop) / 4;\n\t\t        //从下到上依次画\n\t\t        for (int i = 1; i <= 3; i++) {\n\t\t            canvas.drawText(mMinFundMode.dataY + perYValues * i + \"\",\n\t\t                    mPaddingLeft - txtWigth,\n\t\t                    mHeight - mPaddingBottom - perYWidth * i, mXYPaint);\n\t\t        }\n\t\t    }\n\n#### 不长按上面最终收益文字的绘制\n* 我们观察可以发现，默认文字包括：绿色的小圆点、提示文字、收益金额。看似简单的几个字，也需要一个一个处理，准备不同的画笔（当然也可以共用一个画笔）。代码不再给出。\n\n#### 长按上面最终收益文字的绘制\n* 这一块因为需要监测用户的长按状态，会稍微复杂一点。首先需要在`onTouchEvent(MotionEvent event)`获取长按监听：\n\n\t\t @Override\n\t\t    public boolean onTouchEvent(MotionEvent event) {\n\t\t        switch (event.getAction()) {\n\t\t            case MotionEvent.ACTION_DOWN:\n\t\t                mPressTime = event.getDownTime();\n\t\t                break;\n\t\t            case MotionEvent.ACTION_MOVE:\n\t\t                if (event.getEventTime() - mPressTime > DEF_LONGPRESS_LENGTH) {\n\t\t                    Log.e(TAG, \"onTouchEvent: 长按了。。。\");\n\t\t                    mPressX = event.getX();\n\t\t                    mPressY = event.getY();\n\t\t                    //处理长按后的逻辑\n\t\t                    showLongPressView();\n\t\t                }\n\t\t                break;\n\t\t            case MotionEvent.ACTION_UP:\n\t\t                //处理松手后的逻辑\n\t\t                hiddenLongPressView();\n\t\t                break;\n\t\t            default:\n\t\t                break;\n\t\t        }\n\t\t\n\t\t        return true;\n\t\t    }\n\n* 至于长按后的处理，其实并不是在`showLongPressView();`中处理，这里只是去通知onCanves()方法去刷新界面。同时用一个标记位处理是否绘制十字：\n\n\t\t   private void showLongPressView() {\n\t\t        mDrawLongPressPaint = true;\n\t\t        invalidate();\n\t\t    }\n\n\n* 这里有一个问题，仔细观看GIF图，十字的中间位置并不一定是用户手指长按的位置，而是距离按下最近的有效时间点和对应的收益坐标的位置。这样描述可能比较难以理解，这么说吧，比如你点击的是（4,5），但是这一点并没有刚好对应的那一天（因为一天是一个区间，而坐标是一个点），而最近的一天的坐标是（4.1,5.1）。不仅仅x轴不能根据按下的位置确定，并且y轴也不能确认！需要确认到距离按下的最近的有效位置。这里的处理思路是：获取按下的x轴的位置坐标，然后遍历集合中的x轴的时间点所对应的坐标，找到间距最小的有效点，该点的x轴即有效的x轴点。为了简单处理y轴的值，这里保存的是对应点的Model,不用再去处理y轴的有效点。至于绘制十字就可以根据该有效点的x、y轴的坐标去处理：\n\n\t\t /**\n\t\t     * 这里处理画十字的逻辑:这里的十字不是手指按下的位置，这样没有意义。\n\t\t     * 而是当前按下的距离x轴最近的时间（注意：并不一定按下对应的x轴就是有时间的，如果没有取最近的）。\n\t\t     * 当取到x轴的值，之后算出来对应的y轴的值，这个才是十字对应的位置坐标。\n\t\t     * 如何获取x轴最近的时间？我们可以在FundMode中定义x\\y的位置参数，遍历对比找到最小即可。\n\t\t     * (see: drawBrokenPaint(canvas);)\n\t\t     *\n\t\t     * @param canvas\n\t\t     */\n\t\t    private void drawLongPress(Canvas canvas) {\n\t\t        if (!mDrawLongPressPaint) return;\n\t\t\n\t\t        //获取距离最近按下的位置的model\n\t\t        float pressX = mPressX;\n\t\t        //循环遍历，找到距离最短的x轴的mode\n\t\t        FundMode finalFundMode = mFundModeList.get(0);\n\t\t        float minXLen = Integer.MAX_VALUE;\n\t\t        for (int i = 0; i < mFundModeList.size(); i++) {\n\t\t            FundMode currFunMode = mFundModeList.get(i);\n\t\t            float abs = Math.abs(pressX - currFunMode.floatX);\n\t\t            if (abs < minXLen) {\n\t\t                finalFundMode = currFunMode;\n\t\t                minXLen = abs;\n\t\t            }\n\t\t        }\n\t\t\n\t\t        //x\n\t\t        canvas.drawLine(mPaddingLeft, finalFundMode.floatY, mWidth - mPaddingRight, finalFundMode.floatY, mLongPressPaint);\n\t\t        //y\n\t\t        canvas.drawLine(finalFundMode.floatX, mPaddingTop, finalFundMode.floatX, mWidth - mPaddingBottom, mLongPressPaint);\n\t\t\n\t\t        //开始处理按下之后top的文字信息\n\t\t        //先画背景\n\t\t        float hight = mPaddingTop - 30;\n\t\t        Paint bgColor = new Paint(Paint.ANTI_ALIAS_FLAG);\n\t\t        bgColor.setColor(getColor(R.color.color_fundView_pressIncomeTxtBg));\n\t\t        canvas.drawRect(0, 0, mWidth, hight, bgColor);\n\t\t\n\t\t        //开始画按下之后左边的日期文字\n\t\t        Paint timePaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n\t\t        timePaint.setTextSize(mLongPressTextSize);\n\t\t        timePaint.setColor(getColor(R.color.color_fundView_xyTxtColor));\n\t\t        canvas.drawText(processDateTime(finalFundMode.datetime) + \"\",\n\t\t                10, hight / 2 + getFontHeight(mLoadingTextSize, timePaint) / 2, timePaint);\n\t\t\n\t\t        //右边红色收益文字\n\t\t        canvas.drawText(finalFundMode.dataY + \"\",\n\t\t                mWidth - mPaddingRight - mLongPressPaint.measureText(finalFundMode.dataY + \"\"),\n\t\t                hight / 2 + getFontHeight(mLoadingTextSize, timePaint) / 2, mLongPressPaint);\n\t\t\n\t\t        //右边的左边的提示文字\n\t\t        Paint hintPaint = new Paint(Paint.ANTI_ALIAS_FLAG);\n\t\t        hintPaint.setTextSize(mLongPressTextSize);\n\t\t        hintPaint.setColor(getColor(R.color.color_fundView_xyTxtColor));\n\t\t        canvas.drawText(getString(R.string.string_fundView_pressHintTxt),\n\t\t                mWidth - mPaddingRight - mLongPressPaint.measureText(finalFundMode.dataY + \"\")\n\t\t                        - hintPaint.measureText(getString(R.string.string_fundView_pressHintTxt)),\n\t\t                hight / 2 + getFontHeight(mLoadingTextSize, timePaint) / 2, hintPaint);\n\t\t\n\t\t\n\t\t    }\n\n\n* 如何实现蚂蚁金服基金收益的长按后十字延迟消失？这里延迟消失，其实是很好的体验，省的按下的位置不能及时看不到。其实只需要设置一个标记位，当标记为为false时，不执行绘制十字的操作即可：`if (!mDrawLongPressPaint) return;`\n\n\t\t private void hiddenLongPressView() {\n\t\t        //实现蚂蚁金服延迟消失十字线\n\t\t        postDelayed(new Runnable() {\n\t\t            @Override\n\t\t            public void run() {\n\t\t                mDrawLongPressPaint = false;\n\t\t                invalidate();\n\t\t            }\n\t\t        }, 1000);\n\t\t    }\n\n#### 正在加载中文字处理\n* 这里只需要在数据过来之前居中显示一个Text即可：`canvas.drawText(mLoadingText, mWidth / 2 - mLoadingPaint.measureText(mLoadingText) / 2, mHeight / 2, mLoadingPaint);`\n* 那么如何在数据来之后取消这个显示呢？其实所谓取消，直接不执行这个绘制即可（因为重新刷新了界面）。其实和上面十字消失是一样的道理，加一个标记位。\n\n#### code\n* [`https://github.com/scsfwgy/FinancialCustomerView`](https://github.com/scsfwgy/FinancialCustomerView \"https://github.com/scsfwgy/FinancialCustomerView\")\n* 注：该项目会一直维护，不断加入新的关于金融类的各种自定义View。最终的目标是绘制出复杂多变的K线图~\n\n"
  },
  {
    "path": "资料与文档/金融类自定义View（三）--股票分时图(关于细节和实现思路).md",
    "content": "# 金融类自定义View（三）--股票分时图(关于细节和实现思路)\n\n## 前言\n* 本篇文章首先会介绍上一篇文章[上一篇文章](http://blog.csdn.net/wgyscsf/article/details/78632594)遗留下来的问题：长按回调、缩放问题、加载更多等。\n* 剩下的会介绍如何绘制这个分时图，怎么的思路，流程怎样。\n* 建议，先看第二篇文章和对代码进行大致的浏览，不然阅读起来可能会有点吃力。\n\n## 效果图\n\n#### 原【天厚实盘】分时图\n\n* 【天厚实盘】分时图_默认\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E5%88%86%E6%97%B6%E5%9B%BE_%E9%BB%98%E8%AE%A4.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E5%88%86%E6%97%B6%E5%9B%BE_%E9%BB%98%E8%AE%A4.png)\n\n* 【天厚实盘】分时图_长按\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E5%88%86%E6%97%B6%E5%9B%BE_%E9%95%BF%E6%8C%89.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E5%88%86%E6%97%B6%E5%9B%BE_%E9%95%BF%E6%8C%89.png)\n\n* 【天厚实盘】分时图_gif\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E6%BB%91%E5%8A%A8%E6%93%8D%E4%BD%9C.gif?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E6%BB%91%E5%8A%A8%E6%93%8D%E4%BD%9C.gif?raw=true)\n\n#### 仿分时图【TimeSharingView.java】\n\n* 第一阶段，参数准备，外边框、内虚线、折线图等的绘制\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2.png?raw=true)\n\n* 第二阶段，x、y文字、实时横线和实时数据、下方透明阴影\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2_%E5%AE%8C%E5%96%84.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2_%E5%AE%8C%E5%96%84.png)\n\n* 第三阶段，实时数据更新分时图\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E5%AE%9E%E6%97%B6%E6%95%B0%E6%8D%AE%E6%98%BE%E7%A4%BA.gif](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E5%AE%9E%E6%97%B6%E6%95%B0%E6%8D%AE%E6%98%BE%E7%A4%BA.gif)\n\n* 第四阶段，长按十字线，左右移动分时图\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E5%8F%AF%E4%BB%A5%E9%95%BF%E6%8C%89_%E5%8F%AF%E4%BB%A5%E5%B7%A6%E5%8F%B3%E6%8B%96%E5%8A%A8.gif?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E5%8F%AF%E4%BB%A5%E9%95%BF%E6%8C%89_%E5%8F%AF%E4%BB%A5%E5%B7%A6%E5%8F%B3%E6%8B%96%E5%8A%A8.gif?raw=true)\n\n* 第五阶段，长按实时显示详细数据、加载更多处理、实时横线优化、滑动优化\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/dev/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%BA%94%E9%98%B6%E6%AE%B5_%E5%8A%A0%E8%BD%BD%E6%9B%B4%E5%A4%9A.gif](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/dev/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%BA%94%E9%98%B6%E6%AE%B5_%E5%8A%A0%E8%BD%BD%E6%9B%B4%E5%A4%9A.gif)\n\n* 第六阶段，缩放、代码整理、注释\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E5%85%AD%E9%98%B6%E6%AE%B5_%E7%BC%A9%E6%94%BE-%E4%BB%A3%E7%A0%81%E4%BC%98%E5%8C%96-%E6%B3%A8%E9%87%8A.gif?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E5%85%AD%E9%98%B6%E6%AE%B5_%E7%BC%A9%E6%94%BE-%E4%BB%A3%E7%A0%81%E4%BC%98%E5%8C%96-%E6%B3%A8%E9%87%8A.gif?raw=true)\n\t\t\t\n\n\n## 长按回调、缩放问题、加载更多\n#### 长按回调\n* 在上一节，我们已经绘制出了长按的十字，也可以左右滑动。现在的需求是仿照【天厚实盘】长按在View上面绘制出按下点（十字中央）对应点的报价详情以及涨跌幅情况。这个地方的处理，有两种：直接在View上绘制；在布局中设置布局，然后把数据回调给使用者，再设置上对应数据。很明显，第二种方式更简单，也更灵活，这里采用第二种。特别注意需要回调除了当前点，还有上一个点，便于计算涨跌幅。套路：定义接口，设置回调，设置布局。\n\n\t\t//长按的绘制逻辑以及回调\n\t    protected void drawLongPress(Canvas canvas) {\n\t        if (!mDrawLongPressPaint) return;\n\t\t\t\t\n\t\t\t//长按的逻辑\n\t        ....\n\t\n\t        //在这里回调数据信息\n\t        if (mTimeSharingListener != null) {\n\t            int size = mQuotesList.size();\n\t            if ((0 <= finalIndex && finalIndex < size) &&\n\t                    (0 <= finalIndex - 1 && finalIndex - 1 < size))\n\t          //回调,需要两个数据，便于计算涨跌百分比\n\t         mTimeSharingListener.onLongTouch(mQuotesList.get(finalIndex - 1),\n\t                        mQuotesList.get(finalIndex));\n\t        }\n\t    }\n\n#### 长按回调\n* 对于缩放问题的处理，真是操碎了心，思考了好久好久。所谓缩放，我们要知道两手指缩放的距离占View有效宽度的百分比，然后根据百分比计算新的有效可视个数，然后重绘。真的有这么简单吗？我们一直绘制的依据是确定起始位置和结束位置。当两个手指缩小视图时，真正的中心点在两指中间，因此起始位置要变，结束位置也要变。最后采用的方案是采用系统的`ScaleGestureDetector`监听手指，根据`detector.getScaleFactor()`确定缩放因子。缩放思路：所谓缩放，也是计算新的起始位置和结束位置。这里根据缩放因子detector.getScaleFactor()计算新的可见个数（x缩放因子即可）。当放大时，可见的数据集合的个数(A)应该减少。detector.getScaleFactor()(B的范围[1,2)),这个时候可以新的可见数据集合（C）可以考虑采用C=A-A*(B-1);当然这样计算是否准确，还需要商榷。思路简单，但是这里细节比较多，具体可以参考代码。\n\n\t\t//缩放手势监听\n\t    ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener =\n\t            new ScaleGestureDetector.SimpleOnScaleGestureListener() {\n\t                @Override\n\t                public boolean onScale(ScaleGestureDetector detector) {\n\t                    //没有缩放\n\t                    if (detector.getScaleFactor() == 1) return true;\n\t\n\t                    //是放大还是缩小\n\t                    boolean isBigger = detector.getScaleFactor() > 1;\n\t\n\t                    //变化的个数（缩小或者放大），必须向上取整，不然当mShownMaxCount过小时容易取到0。\n\t                    int changeNum = (int) Math.ceil(mShownMaxCount * Math.abs(detector.getScaleFactor() - 1));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//容错处理，省略\n\t                    ...\n\t\n\t                    //计算新的开始位置。这个地方比较难以理解:拉伸了起始点变大，并且是拉伸数量的一半，结束点变小，也是原来的一半。\n\t                    // 收缩，相反。可以自己画一个图看看\n\t                    mBeginIndex = isBigger ? mBeginIndex + helfChangeNum : mBeginIndex - helfChangeNum;\n\t                    if (mBeginIndex < 0) {\n\t                        mBeginIndex = 0;\n\t                    } else if ((mBeginIndex + mShownMaxCount) > mQuotesList.size()) {\n\t                        mBeginIndex = mQuotesList.size() - mShownMaxCount;\n\t                    }\n\t\n\t                    mEndIndex = mBeginIndex + mShownMaxCount;\n\t\n\t                    //只要找好起始点和结束点就可以交给处理重绘的方法就好啦~\n\t                    seekAndCalculateCellData();\n\t                    return true;\n\t                }\n\t\n\t                @Override\n\t                public boolean onScaleBegin(ScaleGestureDetector detector) {\n\t                    Log.e(TAG, \"onScaleBegin: \" + detector.getFocusX());\n\t                    //指头数量，过滤无用手势\n\t                    if (mFingerPressedCount != 2) return true;\n\t                    return true;\n\t                }\n\t            };\n\n\n#### 加载更多\n* 本身，加载更多是很简单的，只要判断移动的时候到最右端就去加载就好。可是，这里牵扯出来另外几个问题\n\t* 滑动到最右边的时候，需要显示右侧的内间距和绘制小圆点（其它情况不需要显示）。\n\t* 不再最右侧的时候，滑动时需要隐藏右侧间距；同时，来新数据后，不应该实时绘制View。\n\t* 滑动到最左边时，需要加载更多。\n\t* 加载更多触发可能在最左侧，但是加载过程中（加载过程可以左右滑动）可能又在最右侧。状态不确定。\n\n* 这里的处理是定义滑动枚举类型，确认实时状态\n\n\t\tenum PullType {\n\t\t        PULL_RIGHT,//向右滑动\n\t\t        PULL_LEFT,//向左滑动\n\t\t        PULL_RIGHT_STOP,//滑动到最右边\n\t\t        PULL_LEFT_STOP,//滑动到最左边\n\t\t    }\n\n* 实时监听并记录状态，并且在触发加载更多时（最好设置一定阀值，比如剩余10个数据时就触发加载更多）\n\n\t\t   /**\n\t\t     * 移动K线图计算移动的单位和重新计算起始位置和结束位置\n\t\t     *\n\t\t     * @param moveLen\n\t\t     */\n\t\t    protected void moveKView(float moveLen) {\n\t\t        //移动之前将右侧的内间距值为0\n\t\t        mInnerRightBlankPadding = 0;\n\t\t\n\t\t        mPullRight = moveLen > 0;\n\t\t        int moveCount = (int) Math.ceil(Math.abs(moveLen) / mPerX);\n\t\t        if (mPullRight) {\n\t\t            int len = mBeginIndex - moveCount;\n\t\t           //阀值\n\t\t            if (len < DEF_MINLEN_LOADMORE) {\n\t\t                //加载更多\n\t\t                if (mTimeSharingListener != null && mCanLoadMore) {\n\t\t                    loadMoreIng();\n\t\t                    mTimeSharingListener.needLoadMore();\n\t\t                }\n\t\t            }\n\t\t             //向右拉逻辑\n\t\t            ...\t\n\t\t            } else {\n\t\t            //向左拉逻辑\n\t\t            ...\n\t\t         }\n\t\t        //确认结束位置\n\t\t        mEndIndex = mBeginIndex + mShownMaxCount;\n\t\t        //开始位置和结束位置确认好，就可以重绘啦~\n\t\t        //Log.e(TAG, \"moveKView: mPullRight：\" + mPullRight + \",mBeginIndex:\" + mBeginIndex + \",mEndIndex:\" + mEndIndex);\n\t\t        seekAndCalculateCellData();\n\t\t    }\t\n\t\t\t\n\t\n\t\n## 分时图绘制思路\n* 整个分时图到这里基本全部完成了，包括如下功能：基本的边框、内部虚线、x/y周文字标示、走势折现、加载更多、左右滑动、滑动数据回调、缩放、实时横线价格展示等。\n* 总代码行数1000+行，完全继承系统View,不依赖任何第三方。虽然也不是很多，但是第一次看肯定是懵逼的。下面大致简述思路。\n* 首先是数据的模拟，为了更加符合真实的使用场景，我们把拿到的数据进行了“转换处理”。可以想象，真实使用场景，不可能你直接从服务端拿到的数据就可以刚好符合View的数据类型。至于获取数据、模拟网络环境、切线程、模拟实时Socket推数据等采用了Rx进行了处理（多说一句，Rx在线程切换真是好用到爆）。\n* 基本点，我们会把拿到数据集合（包括推过来的实时数据）全部存到全局的List<Quotes>中，保证单一数据集合。定义可视范围的起始点mBeginIndex和结束点mEndIndex。有大致了解代码的同学，会看到整个View的大部分操作过程中，主要是计算起始点和结束点，然后重绘View。是的，实时加载数据、左右滑动、缩放、加载更多这些核心功能，其实都是为了计算新的起始位置和结束位置。\n* 核心方法，核心方法全部都在`onDraw(Canvas canvas)`中完成，但是为了逻辑清晰，我们会单独绘制每一个业务功能，保证业务逻辑的清晰，方便修改和扩展。其它的，手势监控在`onTouchEvent(MotionEvent event)`和`ScaleGestureDetector mScaleGestureDetector`中完成。加载数据直接由使用者传递。\n\n\t\t @Override\n\t\t    protected void onDraw(Canvas canvas) {\n\t\t        super.onDraw(canvas);\n\t\t        //Log.e(\"TimeSharingView\", \"onDraw: \");\n\t\t        //默认加载loading界面\n\t\t        showLoadingPaint(canvas);\n\t\t        if (mQuotesList == null || mQuotesList.isEmpty()) {\n\t\t            return;\n\t\t        }\n\t\t        drawOuterLine(canvas);\n\t\t        drawInnerXy(canvas);\n\t\t        drawXyTxt(canvas);\n\t\t        drawBrokenLine(canvas);\n\t\t        //长按处理\n\t\t        drawLongPress(canvas);\n\t\t        //长按情况下的时间和数据框\n\t\t        drawLongPressTxt(canvas);\n\t\t    }\n\n\n* 关于绘图，绘图全部相对于View的左上角开始，在View全局中定义了宽度和高度以及内边距等，基本上在View中绘制任何线和图全部会相对这几个值进行操作，更多的是对位置的准确把握以及对边界的准确控制。\n\n\t\t    //控件宽高，会在onMeasure中进行测量。\n\t\t    int mWidth;\n\t\t    int mHeight;\n\t\t    //上下左右padding，这里不再采用系统属性padding，因为用户容易忘记设置padding,直接在这里更改即可。\n\t\t    float mPaddingTop = 20;\n\t\t    float mPaddingBottom = 50;\n\t\t    float mPaddingLeft = 8;\n\t\t    float mPaddingRight = 90;\n\t\t    //默认情况下结束点距离右边边距\n\t\t    float mInnerRightBlankPadding = DEF_INNER_RIGHT_BLANK_PADDING;\n\t\t    //为了美观，容器内（边框内部的折线图距离外边框线的上下距离）上面有一定间距，下面也有一定的间距。\n\t\t    float mInnerTopBlankPadding = 60;\n\t\t    float mInnerBottomBlankPadding = 60;\n\t\t    \n* 关于y轴最大最小值的确认，这个比较重要。如何保证分时图准确绘制不绘制出边界？如果数据的范围本来是[1,100],突然来了一个10000的数据怎么办？处理的手段是，每次拿到数据之后遍历，找到分时图**可视范围**内的最大值和最小值和View有效高度，算出来单位高度，然后根据每个点的值和最小值（最大值也可以）的差值计算应有的高度坐标即可。如果出现上述中的特别特别大的数据怎么办？那可能就绘制出一条直线咯（生产环境中有遇到）。\n\n* 关于错误和调试，有阅读代码的同学可以在代码中看到大量的Log日志。写的过程中遇到了很多问题，由于有大量的数据还实时推数据并且实时刷新绘制，这个时候可能debug就很难发现问题，直接打Log是有效的手段，可以实时观察到数据的异常。当然，大部分问题直接卡断点就能定位到问题。\n\t\n\n#### code\n* [`https://github.com/scsfwgy/FinancialCustomerView`](https://github.com/scsfwgy/FinancialCustomerView \"https://github.com/scsfwgy/FinancialCustomerView\")\n* 注：该项目会一直维护\n\t* 绘制各种金融类的自定义View。\n\t* 提供金融类自定义View的实现思路。\n\t* 收集整理相关算法、文档以及专业资料。\n* 另，蜡烛图（包括主图指标）大部分功能已经绘制出来啦，代码也进行了大量的重构。在分支：feature_candleview\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\n\n\n\n\n"
  },
  {
    "path": "资料与文档/金融类自定义View（二）--股票分时图.md",
    "content": "## 金融类自定义View（二）--股票分时图\n> 本节主要介绍股票分时图的详细实现思路与遇到的各种问题。该分时图主要包括以下功能：数据的适配、x/y背景轴的绘制、x/轴文字的绘制、长按十字的处理、实时折线的处理、分时折线的左右滑动等。主要会陈述的问题：如何实现最新数据横线的实现、实时数据导致折线的变化的实现思路、折线图左右滑动的处理。（参考阅读：[百度百科--分时图](https://baike.baidu.com/item/%E5%88%86%E6%97%B6%E5%9B%BE/11004740?fr=aladdin \"https://baike.baidu.com/item/%E5%88%86%E6%97%B6%E5%9B%BE/11004740?fr=aladdin\")）\n\n#### 前言\n* 有阅读过第一篇文章的读者可能会说，这特么不和第一篇那个一样嘛。确实，实现思路基本一致，但是复杂度远大于【基金收益自定义view】，包括交互处理与数据处理。\n* 该【股票分时图】当时绘制的时候也没好的分时图进行模仿，就直接拿自己公司同事之前实现的分时图进行了模仿。公司分时图实现是使用了知名的第三方图形库`MPAndroidChart`[https://github.com/PhilJay/MPAndroidChart](https://github.com/PhilJay/MPAndroidChart)。\n* 既然是进行模仿，基本会严格按照原分时图进行实现，读者可以下载原APP对比体验。\n* 有些地方实现并没有严格按照自定义view的套路去实现，比如自定义View属性的抽取、颜色的抽取等（因为真的属性太多了...）,后期会逐步完善抽取。\n* 代码我是尽可能的清晰表达，保证在修改使用的时候可以容易阅读。\n* 本来打算用半年的时候，绘制出自己的金融交易类“K线图”。现在看来，用不了那么久了。因为分时图绘制出来之后，蜡烛图实现就比较简单了--只要在目标点绘制矩形图即可。\n* 代码有点多，enjoy it~\n\n#### 效果图\n###### 原【天厚实盘】分时图\n\n* 【天厚实盘】分时图_默认\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E5%88%86%E6%97%B6%E5%9B%BE_%E9%BB%98%E8%AE%A4.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E5%88%86%E6%97%B6%E5%9B%BE_%E9%BB%98%E8%AE%A4.png)\n\n* 【天厚实盘】分时图_长按\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E5%88%86%E6%97%B6%E5%9B%BE_%E9%95%BF%E6%8C%89.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E5%88%86%E6%97%B6%E5%9B%BE_%E9%95%BF%E6%8C%89.png)\n\n* 【天厚实盘】分时图_gif\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E6%BB%91%E5%8A%A8%E6%93%8D%E4%BD%9C.gif?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%A4%A9%E5%8E%9A%E5%AE%9E%E7%9B%98_%E6%BB%91%E5%8A%A8%E6%93%8D%E4%BD%9C.gif?raw=true)\n\n###### 仿分时图【TimeSharingView.java】\n\n* 第一阶段，参数准备，外边框、内虚线、折线图等的绘制\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2.png?raw=true)\n\n* 第二阶段，x、y文字、实时横线和实时数据、下方透明阴影\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2_%E5%AE%8C%E5%96%84.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/v1.2_%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BE%E9%9B%8F%E5%BD%A2_%E5%AE%8C%E5%96%84.png)\n\n* 第三阶段，实时数据更新分时图\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E5%AE%9E%E6%97%B6%E6%95%B0%E6%8D%AE%E6%98%BE%E7%A4%BA.gif](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E5%AE%9E%E6%97%B6%E6%95%B0%E6%8D%AE%E6%98%BE%E7%A4%BA.gif)\n\n* 第四阶段，长按十字线，左右移动分时图\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E5%8F%AF%E4%BB%A5%E9%95%BF%E6%8C%89_%E5%8F%AF%E4%BB%A5%E5%B7%A6%E5%8F%B3%E6%8B%96%E5%8A%A8.gif?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/timesharing/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E5%8F%AF%E4%BB%A5%E9%95%BF%E6%8C%89_%E5%8F%AF%E4%BB%A5%E5%B7%A6%E5%8F%B3%E6%8B%96%E5%8A%A8.gif?raw=true)\n\n#### 主要运用什么知识\n* 自定义View基础知识\n* 运用Paint绘制文字、绘制横线、绘制矩形\n* 运用Path绘制折线、绘制背景\n* `onTouchEvent(MotionEvent event)`各种手势的监听与处理\n* 【重点】大量的计算、测量以及定位\n* 线程的切换处理（Rxjava,可选）\n\n#### 参考\n* 加载中文字处理、x/y轴曲线的绘制、x轴时间文字和y轴收益文字的定位和绘制、折线的绘制\n、长按十字的处理请参考第一篇文章：[金融类自定义View（一）--仿蚂蚁财富基金收益曲线图](http://blog.csdn.net/wgyscsf/article/details/78446572 \"http://blog.csdn.net/wgyscsf/article/details/78446572\")\n\n\n#### 数据量和位置的确认\n* 对于分时图有一个问题，就是数据的加载和实时推送。因为，对于分时图第一次加载的时候，数据量可能是不确定的，可能第一次拉去过来500条，也可能是100条。同时，分时图中显示的条数也是可变的。比如，分时图中可以显示40条，也可以显示100条。对于自定义分时图来说，两边的数据都不确认。这里的处理思路是，定义全局的数据起始点和结束点，每次刷新页面都会重新计算数据的起始位置和结束位置，同时刚加载的时候和滑动的时候数据的起始位置和结束位置计算方式是不一样的。我们多思考一点，其实所谓的K线图的移动，就是重新寻找数据的起始位置和结束位置，计算好新的开始和结束位置，可以刷新界面了，完成移动操作。\n\n\t\t  /**\n\t\t     * 来最新数据或者刚加载的时候，计算开始位置和结束位置。特别注意，最新的数据在最后面，所以数据范围应该是[(size-mShownMaxCount)~size)\n\t\t     */\n\t\t    private void counterBeginAndEndByNewer() {\n\t\t        int size = mQuotesList.size();\n\t\t        if (size >= mShownMaxCount) {\n\t\t            mBeginIndex = size - mShownMaxCount;\n\t\t            mEndIndex = mBeginIndex + mShownMaxCount;\n\t\t        } else {\n\t\t            mBeginIndex = 0;\n\t\t            mEndIndex = mBeginIndex + mQuotesList.size();\n\t\t        }\n\t\t    }\n\n\n\t\t\t/**\n\t\t     * 移动K线图计算移动的单位和重新计算起始位置和结束位置\n\t\t     * @param moveLen\n\t\t     */\n\t\t    private void moveKView(float moveLen) {\n\t\t        mPullRight = moveLen > 0;\n\t\t        mPullType = moveLen > 0 ? PullType.PULL_RIGHT : PullType.PULL_LEFT;\n\t\t        int moveCount = (int) Math.ceil(Math.abs(moveLen) / mPerX);\n\t\t        if (mPullRight) {\n\t\t            int len = mBeginIndex - moveCount;\n\t\t            if (len < 0) {\n\t\t                mBeginIndex = 0;\n\t\t            } else {\n\t\t                mBeginIndex = len;\n\t\t            }\n\t\t        } else {\n\t\t            int len = mBeginIndex + moveCount;\n\t\t            if (len + mShownMaxCount > mQuotesList.size()) {\n\t\t                mBeginIndex = mQuotesList.size() - mShownMaxCount;\n\t\t            } else {\n\t\t                mBeginIndex = len;\n\t\t                mPullType = PullType.PULL_NONE;//到最左边啦\n\t\t            }\n\t\t        }\n\t\t        mEndIndex = mBeginIndex + mShownMaxCount;\n\t\t        //开始位置和结束位置确认好，就可以重绘啦~\n\t\t        Log.e(TAG, \"moveKView: mPullRight：\" + mPullRight + \",mBeginIndex:\" + mBeginIndex + \",mEndIndex:\" + mEndIndex);\n\t\t        processData();\n\t\t    }\n\n#### 分时图的实时变化\n* 所谓分时图，就是要根据服务推送过来的数据，实时更新折线图。这里的实现采用随机时间模拟服务端推送过来的数据。所谓的折线图实时变化，实现思路其实关键点还是在于数据集合的起始位置和结束位置的确认。确认好起始和结束位置后，重新绘制新的折线即可。因此，该分时图View提供了一个添加单个数据的方法：\n\n\t\t /**\n\t\t     * 实时推送过来的数据，实时更新\n\t\t     *\n\t\t     * @param quotes\n\t\t     */\n\t\t    public void addTimeSharingData(Quotes quotes) {\n\t\t        if (quotes == null) {\n\t\t            Toast.makeText(mContext, \"数据异常\", Toast.LENGTH_SHORT).show();\n\t\t            Log.e(TAG, \"setTimeSharingData: 数据异常\");\n\t\t            return;\n\t\t        }\n\t\t        mQuotesList.add(quotes);\n\t\t        //如果实在左右移动，则不去实时更新K线图，但是要把数据加进去\n\t\t        if (mPullType == PullType.PULL_NONE) {\n\t\t            Log.e(TAG, \"addTimeSharingData: 处理实时更新操作...\");\n\t\t            counterBeginAndEndByNewer();\n\t\t            processData();\n\t\t        }\n\t\t    }\n\n#### 折线图的绘制和折线图阴影的处理\n* 由上面两点可以看出，只要有起始位置和结束位置，不仅可以绘制好折线还可以实时更新，那么折线图的绘制就要求很高了。同时，我们可以注意一下，折线图下面的阴影，这个阴影怎么处理？查找了很多资料，并没有Path绘制折线并且绘制不同颜色的背景的处理；并且，折线并不是完整的闭环，而是只有上方一部分。这个地方思考了很久，最终的解决方案是，采用两个Path，第一个Path只绘制用户看到的折线图，同时设置画笔属性`mBrokenLinePaint.setStyle(Paint.Style.STROKE);`，只绘制折线，不填充内容。另外提供一个Path，只绘制内容，设置画笔属性：`mBrokenLineBgPaint.setStyle(Paint.Style.FILL);`，另外提供透明效果：`mBrokenLineBgPaint.setAlpha(mAlpha);`，这样就实现了这种效果：\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BEpath.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/%E5%88%86%E6%97%B6%E5%9B%BE_%E6%8A%98%E7%BA%BF%E5%9B%BEpath.png?raw=true)\n\n\t\t//折线图绘制核心代码\n\t\t private void drawBrokenLine(Canvas canvas) {\n\t\t        //先画第一个点\n\t\t        Quotes quotes = mQuotesList.get(mBeginIndex);\n\t\t        Path path = new Path();\n\t\t        Path path2 = new Path();\n\t\t        //这里需要说明一下，x轴的起始点，其实需要加上mPerX，但是加上之后不是从起始位置开始，不好看。\n\t\t        // 同理，for循环内x轴其实需要(i+1)。现在这样处理，最后会留一点空隙，其实挺好看的。\n\t\t        float floatY = (float) (mHeight - mPaddingBottom - mInnerBottomBlankPadding - mPerY * (quotes.c - mMinQuotes.c));\n\t\t        //在自定义view:FundView中的位置坐标\n\t\t        //记录下位置信息\n\t\t        quotes.floatX = mPaddingLeft;\n\t\t        quotes.floatY = floatY;\n\t\t        path.moveTo(mPaddingLeft, floatY);\n\t\t        path2.moveTo(mPaddingLeft, floatY);\n\t\t        for (int i = mBeginIndex + 1; i < mEndIndex; i++) {\n\t\t            Quotes q = mQuotesList.get(i);\n\t\t            float floatX2 = mPaddingLeft + mPerX * (i - mBeginIndex);//注意这个 mPerX * (i-mBeginIndex)，而不是mPerX * (i)\n\t\t            float floatY2 = (float) (mHeight - mPaddingBottom - mInnerBottomBlankPadding - mPerY * (q.c - mMinQuotes.c));\n\t\t            //记录下位置信息\n\t\t            q.floatX = floatX2;\n\t\t            q.floatY = floatY2;\n\t\t            path.lineTo(floatX2, floatY2);\n\t\t            path2.lineTo(floatX2, floatY2);\n\t\t            //最后一个点，画一个小圆点；实时横线；横线的右侧数据与背景；折线下方阴影\n\t\t            if (i == mEndIndex - 1) {\n\t\t                //绘制小圆点\n\t\t                canvas.drawCircle(floatX2, floatY2, mDotRadius, mDotPaint);\n\t\t\n\t\t                //接着画实时横线\n\t\t                canvas.drawLine(mPaddingLeft, floatY2, mWidth - mPaddingRight, floatY2, mTimingLinePaint);\n\t\t\n\t\t                //接着绘制实时横线的右侧数据与背景\n\t\t                //文字高度\n\t\t                float txtHight = getFontHeight(mTimingTxtWidth, mTimingTxtBgPaint);\n\t\t                //绘制背景\n\t\t                canvas.drawRect(mWidth - mPaddingRight, floatY2 - txtHight / 2, mWidth, floatY2 + txtHight / 2, mTimingTxtBgPaint);\n\t\t\n\t\t                //绘制实时数据\n\t\t                //距离左边的距离\n\t\t                float leftDis = 8;\n\t\t                canvas.drawText(FormatUtil.numFormat(q.c, mDigits), mWidth - mPaddingRight + leftDis, floatY2 + txtHight / 4, mTimingTxtPaint);\n\t\t\n\t\t                //在这里把path圈起来，添加阴影。特别注意，这里处理下方阴影和折线边框。采用两个画笔和两个Path处理的，貌似没有一个Paint可以同时绘制边框和填充色\n\t\t                path2.lineTo(floatX2, mHeight - mPaddingBottom);\n\t\t                path2.lineTo(mPaddingLeft, mHeight - mPaddingBottom);\n\t\t                path2.close();\n\t\t            }\n\t\t        }\n\t\t        canvas.drawPath(path, mBrokenLinePaint);\n\t\t        canvas.drawPath(path2, mBrokenLineBgPaint);\n\t\t    }\n\n#### 折线图的左右滑动处理\n* 这个功能的实现考虑了很久，不知道怎么实现。当时还在考虑安卓的画布是否会提供类似于ScrollView的功能，可以绘制很多View,然后可以左右滑动View;或者类似于ListView....(并没有)\n* 最终的实现思路是这样的（有线上运行的分时图是这样处理的，可以放心使用！）：\n\t0. 监听滑动\n\t1. 手指滑动的时候，记录下滑动的x轴的距离\n\t2. 根据单位数据的x轴的距离，计算出需要移动几个单位的数据（注意边界和方向问题）\n\t3. 根据移动的单位，重新计算起始位置和结束位置(其实最上面的起始位置和结束位置的确认，是在这里得到启发的)\n\t4. 刷新View\n\n\n\t\t\t\t//监听判断手指移动\n\t\t\t\t@Override\n\t\t\t    public boolean onTouchEvent(MotionEvent event) {\n\t\t\t        switch (event.getAction()) {\n\t\t\t            case MotionEvent.ACTION_DOWN:\n\t\t\t                mPressedX = event.getX();\n\t\t\t                mPressTime = event.getDownTime();\n\t\t\t                //按下的手指个数\n\t\t\t                mFingerPressedCount = event.getPointerCount();\n\t\t\t                break;\n\t\t\t            case MotionEvent.ACTION_MOVE:\n\t\t\t                \n\t\t\t\t\t\t\t...\n\n\t\t\t                //判断是否是手指移动\n\t\t\t                float currentPressedX = event.getX();\n\t\t\t                float moveLen = currentPressedX - mPressedX;\n\t\t\t                //重置当前按下的位置【不要忘了】\n\t\t\t                mPressedX = currentPressedX;\n\t\t\t                if (Math.abs(moveLen) > DEF_PULL_LENGTH && mFingerPressedCount == 1) {\n\t\t\t                    Log.e(TAG, \"onTouchEvent: 正在移动分时图\");\n\t\t\t                    //移动k线图\n\t\t\t                    moveKView(moveLen);\n\t\t\t                }\n\t\t\t                break;\n\t\t\t          \t...\n\t\t\t         \t\t\n\t\t\t    }\n\n\n\t\t\t\t /**\n\t\t\t     * 移动K线图计算移动的单位和重新计算起始位置和结束位置\n\t\t\t     * @param moveLen\n\t\t\t     */\n\t\t\t    private void moveKView(float moveLen) {\n\t\t\t        mPullRight = moveLen > 0;\n\t\t\t        mPullType = moveLen > 0 ? PullType.PULL_RIGHT : PullType.PULL_LEFT;\n\t\t\t        int moveCount = (int) Math.ceil(Math.abs(moveLen) / mPerX);\n\t\t\t        if (mPullRight) {\n\t\t\t            int len = mBeginIndex - moveCount;\n\t\t\t            if (len < 0) {\n\t\t\t                mBeginIndex = 0;\n\t\t\t            } else {\n\t\t\t                mBeginIndex = len;\n\t\t\t            }\n\t\t\t        } else {\n\t\t\t            int len = mBeginIndex + moveCount;\n\t\t\t            if (len + mShownMaxCount > mQuotesList.size()) {\n\t\t\t                mBeginIndex = mQuotesList.size() - mShownMaxCount;\n\t\t\t            } else {\n\t\t\t                mBeginIndex = len;\n\t\t\t                mPullType = PullType.PULL_NONE;//到最左边啦\n\t\t\t            }\n\t\t\t        }\n\t\t\t        mEndIndex = mBeginIndex + mShownMaxCount;\n\t\t\t        //开始位置和结束位置确认好，就可以重绘啦~\n\t\t\t        Log.e(TAG, \"moveKView: mPullRight：\" + mPullRight + \",mBeginIndex:\" + mBeginIndex + \",mEndIndex:\" + mEndIndex);\n\t\t\t        //这里就是处理和刷新数据\n\t\t\t\t\tprocessData();\n\t\t\t    }\n\n\n#### 待处理的问题\n* 长按十字，上方应该显示：开盘价、收盘价、最高价、最低价、时间等信息；这里不再将这一块在View中绘制，而是在xml中进行绘制即可。该View其实很简单，只需要提供一个接口，把点击长按的数据回调出去就好~\n* 双指View缩放的处理，这里当时考虑很难处理的。但是，现在已经有思路了：改变显示的View的数据量，同时找到中间位置，以该位置左右加减指定的数据量，刷新界面即可！\n* 滑动到最左边，加载更多数据....\n* 手指滑动、更新数据都会导致整个View的重新绘制，可能短时间内会导致N次重绘，感觉严重影响性能。但是，问了一些朋友，貌似都是这样处理的。。。没有其它方式吗？\n* 打个广告，公司一直在**招聘**，java、DBA、H5、Devlops等，坐标：上海，欢迎来投：[天厚投资 Tophold](https://www.lagou.com/gongsi/j3720.html)\n\n#### code\n* [`https://github.com/scsfwgy/FinancialCustomerView`](https://github.com/scsfwgy/FinancialCustomerView \"https://github.com/scsfwgy/FinancialCustomerView\")\n* 注：该项目会一直维护，不断加入新的关于金融类的各种自定义View。最终的目标是绘制出复杂多变的K线图~\n\n"
  },
  {
    "path": "资料与文档/金融类自定义View（四）--股票蜡烛图以及MA、BOLL指标.md",
    "content": "# 金融类自定义View（四）--股票蜡烛图(包含MA、BOLL指标)以及代码重构\n\n## 前言\n* 本文只描述蜡烛图单独的绘制逻辑，至于和分时图相同的逻辑不再阐述，感兴趣的可以查看之前的文章，会有详细的阐述。\n* 首先会介绍蜡烛图的绘制思路、MA/BOLL指标的绘制、指标y轴越界问题、x轴绘制的细节处理。\n* 最后会介绍一下代码的重构处理以及对后期副图部分的绘制影响。\n\n## 效果图\n\n#### 蜡烛图【MasterView.java】\n\n* 默认蜡烛图\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E8%9C%A1%E7%83%9B%E5%9B%BE.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5_%E8%9C%A1%E7%83%9B%E5%9B%BE.png)\n\n* MA指标（BOLL类似）\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_ma_nopress.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_ma_nopress.png)\n\n* 蜡烛图长按\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_ma_press.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_ma_press.png)\n\n* gif\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_gif.gif](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/feature_candleview/img/%E8%9C%A1%E7%83%9B%E5%9B%BE_%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5_gif.gif)\n\n\n## 蜡烛图绘制\n#### 命名\n* 主流的交易曲线图会包含两个大部分，上面一大块是走势图，包含分时图、5分图、15分图、日k、周k、月k等；下面一小块是指标，包含成交量、MACD、KDJ、RSI等。如下图，是同花顺的交易曲线图，基本也是这样构成的：\n\n\n![https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/master/img/%E5%90%8C%E8%8A%B1%E9%A1%BA%E4%BA%A4%E6%98%93%E5%9B%BE.png](https://raw.githubusercontent.com/scsfwgy/FinancialCustomerView/master/img/%E5%90%8C%E8%8A%B1%E9%A1%BA%E4%BA%A4%E6%98%93%E5%9B%BE.png)\n\n* 因此，在本项目命名如下，整个交易曲线图称为KView,上面的部分称为MasterView(主图，包含分时图和蜡烛图)；下面的部分称为MinorView(副图，包含各种副图指标)。其中蜡烛图又包含MA(5,10,20)、BOLL(26)、MA(5,10,20)\\BOLL(26)三种指标，对于副图部分，计划只绘制以下三种指标，和【天厚实盘】APP保持同步：MACD(12,26,9)、RSI(6,12,24)、KDJ(9,3,3)。\n\n#### 蜡烛图的绘制\n* 仅仅是蜡烛图的绘制很简单，之前绘制好分时图就说过这个问题。蜡烛图的矩形Y轴是根据开盘价格和闭市价格绘制对应的高度，至于哪个在上哪个在下不确定。X轴的绘制是在原来分时图目标点向左向右分别取1/2.0个单元大小。对于蜡烛间间距的处理，这里采用倍率的处理方式，间距是单个蜡烛宽度的0.1f（为什么不采用固定大小？当缩放蜡烛图时如果间距固定大小会非常丑）。至于蜡烛图Y轴中间的横线则是根据最高价和最低价对应的高度进行绘制。\n* 蜡烛图的绘制如下，特别注意边界的处理，当处理可视范围内第一个Quotes时leftRectX、leftLineX必须判断和左边界的关系，取最大的，不然在界面的表现就是蜡烛图会绘制出左边界。同理，可视范围内结束点也需要考虑这个问题，同时，右侧有一个内边距需要考虑进去。\n\n\n\t\t    /**\n\t\t     * 绘制蜡烛图\n\t\t     * @param canvas\n\t\t     * @param diverWidth 蜡烛图之间的间距\n\t\t     * @param List index\n\t\t     * @param quotes 目标Quotes\n\t\t     */\n\t\t    private void drawCandleViewProcess(Canvas canvas, float diverWidth, int i, \t\t\t\t\tQuotes quotes) {\n\t\t       //异常拦截以及参数设置\n\t\t        ...\n\t\t        \n\t\t        //定位蜡烛矩形的四个点\n\t\t        topRectY = (float) (mPaddingTop + mInnerTopBlankPadding +\n\t\t                mPerY * (mCandleMaxY - quotes.o));\n\t\t        bottomRectY = (float) (mPaddingTop + mInnerTopBlankPadding +\n\t\t                mPerY * (mCandleMaxY - quotes.c));\n\t\t        leftRectX = -mPerX / 2 + quotes.floatX + diverWidth / 2;\n\t\t        rightRectX = mPerX / 2 + quotes.floatX - diverWidth / 2;\n\t\t\n\t\t        //定位单个蜡烛中间线的四个点\n\t\t        leftLineX = quotes.floatX;\n\t\t        topLineY = (float) (mPaddingTop + mInnerTopBlankPadding +\n\t\t                mPerY * (mCandleMaxY - quotes.h));\n\t\t        rightLineX = quotes.floatX;\n\t\t        bottomLineY = (float) (mPaddingTop + mInnerTopBlankPadding +\n\t\t                mPerY * (mCandleMaxY - quotes.l));\n\t\t\n\t\t        RectF rectF = new RectF();\n\t\t        //边界处理\n\t\t        if (i == mBeginIndex) {\n\t\t            leftRectX = leftRectX < mPaddingLeft ? mPaddingLeft : leftRectX;\n\t\t            leftLineX = leftLineX < mPaddingLeft ? mPaddingLeft : leftLineX;\n\t\t        } else if (i == (mEndIndex - 1)) {\n\t\t            rightRectX = rightRectX > mWidth - mPaddingRight ? mWidth - mPaddingRight : rightRectX;\n\t\t            rightLineX = rightLineX > mWidth - mPaddingRight ? mWidth - mPaddingRight : rightLineX;\n\t\t        }\n\t\t        rectF.set(leftRectX, topRectY, rightRectX, bottomRectY);\n\t\t        //设置颜色\n\t\t        mCandlePaint.setColor(quotes.c > quotes.o ? mRedCandleColor : mGreenCandleColor);\n\t\t        \n\t\t        //绘制蜡烛图\n\t\t        canvas.drawRect(rectF, mCandlePaint);\n\t\t\n\t\t        //开始画low、high线\n\t\t        canvas.drawLine(leftLineX, topLineY, rightLineX, bottomLineY, mCandlePaint);\n\t\t    }\n\t\t    \n\t\t \n#### MA、BOLL的绘制\n* MA、BOLL是在主图的指标表现,可以辅助用户在交易中做出策略指导。链接：[百度百科：移动平均线(MA)](https://baike.baidu.com/item/%E7%A7%BB%E5%8A%A8%E5%B9%B3%E5%9D%87%E7%BA%BF/217887?fr=aladdin&fromid=1511750&fromtitle=MA)，[百度百科：布林线(BOLL)](https://baike.baidu.com/item/%E5%B8%83%E6%9E%97%E7%BA%BF/3424486?fr=aladdin)\n* 在本项目中MA取最常用的5单位、10单位、20单位，简称MA(5,10,20);BOLL取常用的26单位，简称BOLL(26)。当然，在本项目中到的各种指标算法全部都抽取出来，在FinancialAlgorithm.java中。一般指标算法都是比较繁琐的，要么是多日均值，要么就是加权等等，所以对算法要求尽可能的高效。下面是MA的计算，之前写的是采用双重循环，改后之后只要一层即可，尽可能避免多重循环。\n\n\n\t    /**\n\t     * MA算法，period（周期）的MA的计算：带上今天，向前取period的收盘价之和除以period,即是今日的MA(period)。\n\t     * 算法很简洁，但是是对的。\n\t     *\n\t     * @param period 周期，一般是：5、10、20、30、60\n\t     */\n\t    public static void calculateMA(List<Quotes> quotesList, int period) {\n\t        if (quotesList == null || quotesList.isEmpty()) return;\n\t        if (period < 0 || period > quotesList.size() - 1) return;\n\t\n\t        double sum1 = 0;\n\t        for (int i = 0; i < quotesList.size(); i++) {\n\t            Quotes quotes = quotesList.get(i);\n\t            sum1 += quotes.c;\n\t            //边界\n\t            if (i < period - 1) {\n\t                continue;\n\t            }\n\t\n\t            if (i > period - 1) {\n\t                sum1 -= quotesList.get(i - period).c;//减去之前算过的。\n\t            }\n\t\n\t            if (period == 5) {\n\t                quotes.ma5 = sum1 / period;\n\t            } else if (period == 10) {\n\t                quotes.ma10 = sum1 / period;\n\t            } else if (period == 20) {\n\t                quotes.ma20 = sum1 / period;\n\t            } else {\n\t                Log.e(TAG, \"calculateMA: 没有该种period，TODO:完善Quotes\");\n\t                return;\n\t            }\n\t\n\t        }\n\t    }\n\n* 对于主图指标的切换，采用的是单击click，四种类型。对于指标的绘制其实就是绘制Path，只要能确认x轴和y轴对应坐标即可。对于x轴上文已经说了，取单个蜡烛的x方向即可。对于y轴，这里取的是对应Quotes的MA值，当然这里的MA有三种MA5、MA10、MA20,因此画出来也是三条线。有心的同学看上面计算MA的算法有一个判断`if (i < period - 1) {continue;}`，对于`i < period - 1`直接就continue，意味着就没有对应的MA值。是的，对于数据集合当开始的时候是没有MA值的，有些资料会取一些默认值进行显示，这里的处理方式是不进行计算，在View的效果就是不绘制（效果如下图）。BOLL同理。\n\n\n\t \t/**\n\t     * 主图上面的技术指标类型\n\t     */\n\t    public enum MasterType {\n\t        NONE,//无\n\t        MA,//MA5、10、20\n\t        BOLL,//BOLL(26)\n\t        MA_BOLL//MA5、10、20和BOLL(26)同时展示\n\t    }\n\n    \t\n\t\tprivate void drawMa(Canvas canvas) {\n\t\t        //参数初始化\n\t\t        ...\n\t\t        \n\t\t        for (int i = mBeginIndex; i < mEndIndex; i++) {\n\t\t            Quotes quotes = mQuotesList.get(i);\n\t\t            //在绘制蜡烛图的时候已经计算了\n\t\t            float floatX = quotes.floatX;\n\t\t\n\t\t\t\t\t  //绘制MA5的逻辑\n\t\t            float floatY = getMasterDetailFloatY(quotes, MasterDetailType.MA5);\n\t\t\n\t\t            //异常,在View的行为就是不显示而已，影响不大。一般都是数据的开头部分。\n\t\t            if (floatY == -1) continue;\n\t\t\n\t\t            if (isFirstMa5) {\n\t\t                isFirstMa5 = false;\n\t\t                path5.moveTo(floatX, floatY);\n\t\t            } else {\n\t\t                path5.lineTo(floatX, floatY);\n\t\t            }\n\t\t\t\t\t\n\t\t\t\t\t\t//这里是绘制MA10/20的逻辑，和MA5一样\n\t\t\t\t\t\t...\n\t\t           \n\t\t          }\n\t\t\n\t\t        canvas.drawPath(path5, mMa5Paint);\n\t\t        canvas.drawPath(path10, mMa10Paint);\n\t\t        canvas.drawPath(path20, mMa20Paint);\n\t\t    }    \t\n\n    \t\n ![https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/MA%E6%8C%87%E6%A0%87%E8%BE%B9%E7%95%8C.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/MA%E6%8C%87%E6%A0%87%E8%BE%B9%E7%95%8C.png?raw=true)\n    \t\n\n#### 越界问题\n* 在开始之前看以下两个截图，对于同一个时刻一个不展示BOLL线，一个展示BOLL线，绘制出来的蜡烛图折线图是“不一样”的。\n\n ![https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/%E6%9C%89boll%E5%92%8C%E6%B2%A1%E6%9C%89boll%E5%AF%B9%E6%AF%94%E5%9B%BE.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/%E6%9C%89boll%E5%92%8C%E6%B2%A1%E6%9C%89boll%E5%AF%B9%E6%AF%94%E5%9B%BE.png?raw=true)\n \n * 这并不是绘制错误，而是特意的处理。在绘制分时图的时候，我们对于Y轴的mPerY的计算是根据可视范围内数据集合的收盘价最大值和最小值以及Y轴有效高度计算的。这样的处理可以保证无论分时图浮动多大，可以保证分时图不会绘制出边界。分时图“值”比较单一，只需要考虑一个收盘价即可。可是，对于蜡烛图需要考虑的就比较多了，如果还是仅仅通过收盘价计算最小值和最大值，就会导致如果计算出来的“待显示的点”如果远远大于收盘价，就会导致“越界”！并且，这种情况，确实在开发过程中遇到了。因此，对于蜡烛图最大值和最小值的判断，需要遍历单个Quotes,寻找到最大和最小值。通过观察线上应用【天厚实盘】以及同花顺基本上都是这样处理的：随着主图上指标的变化，蜡烛图显示的高度并不一致，为的就是保证“不越界”。以下是寻找单个Quotes中最大值的过程，特别注意，if判断逻辑不能用`else if`，这个错误调试了几个小时才找到！\n\n \n\t\t\t  /**\n\t\t\t     * 找到单个报价中的最大值\n\t\t\t     *\n\t\t\t     * @param quotes\n\t\t\t     * @param masterType\n\t\t\t     * @return\n\t\t\t     */\n\t\t\t    public static double getMasterMaxY(Quotes quotes, MasterView.MasterType masterType) {\n\t\t\t        double max = Integer.MIN_VALUE;\n\t\t\t        //ma\n\t\t\t        //只有在存在ma的情况下才计算\n\t\t\t        if (masterType == MasterView.MasterType.MA || masterType == MasterView.MasterType.MA_BOLL) {\n\t\t\t            if (quotes.ma5 != 0 && quotes.ma5 > max) {\n\t\t\t                max = quotes.ma5;\n\t\t\t            }\n\t\t\t            if (quotes.ma10 != 0 && quotes.ma10 > max) {\n\t\t\t                max = quotes.ma10;\n\t\t\t            }\n\t\t\t            if (quotes.ma20 != 0 && quotes.ma20 > max) {\n\t\t\t                max = quotes.ma20;\n\t\t\t            }\n\t\t\t        }\n\t\t\t\n\t\t\t        //boll\n\t\t\t        if (masterType == MasterView.MasterType.BOLL || masterType == MasterView.MasterType.MA_BOLL) {\n\t\t\t            if (quotes.mb != 0 && quotes.mb > max) {\n\t\t\t                max = quotes.mb;\n\t\t\t            }\n\t\t\t            if (quotes.up != 0 && quotes.up > max) {\n\t\t\t                max = quotes.up;\n\t\t\t            }\n\t\t\t            if (quotes.dn != 0 && quotes.dn > max) {\n\t\t\t                max = quotes.dn;\n\t\t\t            }\n\t\t\t        }\n\t\t\t        //quotes\n\t\t\t        if (quotes.h != 0 && quotes.h > max) {\n\t\t\t            max = quotes.h;\n\t\t\t        }\n\t\t\t        //没有找到\n\t\t\t        if (max == Integer.MIN_VALUE) {\n\t\t\t            max = 0;\n\t\t\t        }\n\t\t\t        return max;\n\t\t\t\n\t\t\t    } \n\n\n## 代码重构\n* 其实在分时图绘制完毕之后打算先整副图部分的，后来发现各种指标算法比较烦人，就直接上手蜡烛图了。\n* 随着View功能、交互的的增加，代码量也大量激增，在分时图功能完成时整个View的代码行数已经过1000行了，感觉多的都没法维护了=。=，因此考虑对代码进行重构。\n* 在开始绘制绘制蜡烛图之前，对代码进行了大量的重构，将一些公共的逻辑抽离到了父类，尽可能减少子类中的业务逻辑。什么是公共的逻辑？比如边距、单机长按阀值、背景、边框等等很多属性其实主图和副图都是一样的，也有部分一样的，可以分开对待，比如主图需要绘制x/y内虚线，而副图只需要绘制y轴的虚线即可。当然，还有一些父类没法实现的，可以考虑将方法抽象化，让子类去实现业务逻辑。\n* 整个继承关系如下\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/view%E7%BB%A7%E6%89%BF%E5%85%B3%E7%B3%BB.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/view%E7%BB%A7%E6%89%BF%E5%85%B3%E7%B3%BB.png?raw=true)\n\n* 在处理的时候，把和业务没有关系的View逻辑放到了BaseFinancialView中，比如各种常量的获取、View宽高的测量、以及View的工具类等。而在KView.java中则是处理主图和副图全部都有（或者部分有）的共有属性。对于部分有的特性，比如副图没有x轴的虚线绘制，可以用一个开关在父类中处理是否绘制，开关可以由子类控制。\n\n\t\t\t    /**\n\t\t\t     * 绘制内部x/y轴虚线\n\t\t\t     * @param canvas\n\t\t\t     */\n\t\t\t    protected void drawInnerXy(Canvas canvas) {\n\t\t\t        if (isShowInnerX())\n\t\t\t            drawInnerX(canvas);\n\t\t\t        if (isShowInnerY())\n\t\t\t            drawInnerY(canvas);\n\t\t\t    }\n\t\t\t    \n* 代码继承关系整好之后，一些线基本就OK了，下面是副图的截图，基本没有做任何处理，就可以直接显示了\n\n![https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/%E5%89%AF%E5%9B%BE_def.png?raw=true](https://github.com/scsfwgy/FinancialCustomerView/blob/master/img/%E5%89%AF%E5%9B%BE_def.png?raw=true)\n\t\t\t    \n* 而一些父类没法实现具体逻辑的，可以直接声明为抽象类，让子类去实现即可。\n\n\t\t   /**\n\t\t     * 父类：寻找边界和计算单元数据大小。寻找:x轴开始位置数据和结束位置的model、y轴的最大数据和最小数据对应的model；\n\t\t     * 计算x/y轴数据单元大小。这个交给子类去实现，一般情况下寻找边界需要遍历，在父类中遍历没有意义，\n\t\t     * 因为不知道子类还有什么遍历需求。因此改为抽象方法，子类实现。子类必须完成寻找边界的任务。\n\t\t     */\n\t\t    protected abstract void seekAndCalculateCellData();\n    \n \t\t\t-------------------------------------------------------   \n    \n    \t\t//MasterView实现具体逻辑。\n\t\t \t@Override\n\t\t    protected void seekAndCalculateCellData() {\n\t\t        if (mQuotesList.isEmpty()) return;\n\t\t\n\t\t        //对于蜡烛图，需要计算以下指标。\n\t\t        if (mViewType == ViewType.CANDLE) {\n\t\t           //指标算法\n\t\t           ...\n\t\t        }\n\t\t\n\t\t\n\t\t        //寻找边界和计算单元数据大小\n\t\t        ...\n\t\t        \n\t\t        //计算mPerX、mPerY\t\t\n\t\t       ...\n\t\t       \t\t\n\t\t        //重绘\n\t\t        invalidate();\n\t    \t\t}\n\n* 通过代码重构的手段，实现了在分时图、蜡烛图以及蜡烛图对应指标、其它各种交互共存的情况下，MasterView的代码行数还是维持在1000多行，MasterView基本没有增加代码量。现在存在的问题是，仍然存在各种各样的属性散列在View中，感觉难以控制。MP作者PhilJay在处理这个问题是将所有属性聚合成一个对象，在使用时可能会有很多层调用，但是在使用者（开发者）层面，看到的只有一个对象，然后控制着View的各种表现。在下一阶段重构的过程中，会考虑属性的处理方式是否也采用这种方式。\n\n\n#### code\n* [`https://github.com/scsfwgy/FinancialCustomerView`](https://github.com/scsfwgy/FinancialCustomerView \"https://github.com/scsfwgy/FinancialCustomerView\")\n* 注：该项目会一直维护\n\t* 绘制各种金融类的自定义View。\n\t* 提供金融类自定义View的实现思路。\n\t* 收集整理相关算法、文档以及专业资料。\n\t* 代码进行了大量重构。\n\t* 蜡烛图绘制完毕。\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\n\n\n\n\n"
  }
]