diff --git a/exampleApp/build.gradle b/exampleApp/build.gradle index 36437c5..00ad6cf 100644 --- a/exampleApp/build.gradle +++ b/exampleApp/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - compileSdkVersion 27 + compileSdkVersion 28 lintOptions { disable 'InvalidPackage' @@ -12,7 +12,7 @@ android { defaultConfig { applicationId "it.trade.android.exampleapp" minSdkVersion 19 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -29,11 +29,11 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:multidex:1.0.3' - implementation 'com.android.support:customtabs:27.1.1' - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support:customtabs:28.0.0' + implementation 'com.android.support:appcompat-v7:28.0.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation project(':tradeit-android-sdk') - androidTestImplementation 'com.android.support:support-annotations:27.1.1' + androidTestImplementation 'com.android.support:support-annotations:28.0.0' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-web:3.0.2' androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3' diff --git a/exampleApp/src/androidTest/java/it/trade/android/exampleapp/MainActivityTest.java b/exampleApp/src/androidTest/java/it/trade/android/exampleapp/MainActivityTest.java index cd96fba..09b1fec 100644 --- a/exampleApp/src/androidTest/java/it/trade/android/exampleapp/MainActivityTest.java +++ b/exampleApp/src/androidTest/java/it/trade/android/exampleapp/MainActivityTest.java @@ -6,13 +6,13 @@ import android.support.test.InstrumentationRegistry; import android.support.test.espresso.ViewInteraction; import android.support.test.espresso.action.ViewActions; +import android.support.test.filters.LargeTest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObject; import android.support.test.uiautomator.UiObjectNotFoundException; import android.support.test.uiautomator.UiSelector; -import android.test.suitebuilder.annotation.LargeTest; import android.widget.Button; import android.widget.EditText; diff --git a/exampleAppJapan/.gitignore b/exampleAppJapan/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/exampleAppJapan/.gitignore @@ -0,0 +1 @@ +/build diff --git a/exampleAppJapan/build.gradle b/exampleAppJapan/build.gradle new file mode 100644 index 0000000..5cab1fe --- /dev/null +++ b/exampleAppJapan/build.gradle @@ -0,0 +1,41 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "it.trade.android.japanapp" + minSdkVersion 19 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + sourceSets { + main.java.srcDirs += "src/main/kotlin" + test.java.srcDirs += "src/test/kotlin" + androidTest.java.srcDirs += "src/androidTest/kotlin" + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'android.arch.lifecycle:extensions:1.1.1' + implementation 'com.android.support:design:28.0.0' + implementation project(':tradeit-android-sdk') + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/exampleAppJapan/proguard-rules.pro b/exampleAppJapan/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/exampleAppJapan/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/exampleAppJapan/src/androidTest/kotlin/it/trade/android/japanapp/ExampleInstrumentedTest.kt b/exampleAppJapan/src/androidTest/kotlin/it/trade/android/japanapp/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..66f9d4d --- /dev/null +++ b/exampleAppJapan/src/androidTest/kotlin/it/trade/android/japanapp/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package it.trade.android.japanapp + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("it.trade.android.japanapp", appContext.packageName) + } +} diff --git a/exampleAppJapan/src/main/AndroidManifest.xml b/exampleAppJapan/src/main/AndroidManifest.xml new file mode 100644 index 0000000..929f38d --- /dev/null +++ b/exampleAppJapan/src/main/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/MainActivity.kt b/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/MainActivity.kt new file mode 100644 index 0000000..db4e803 --- /dev/null +++ b/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/MainActivity.kt @@ -0,0 +1,23 @@ +package it.trade.android.japanapp + +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import it.trade.android.japanapp.R +import it.trade.android.japanapp.ui.orderinput.OrderInputFragment + +class MainActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.main_activity) + if (savedInstanceState == null) { + supportFragmentManager.beginTransaction() + // TODO this symbol is only for testing. and it's chosen as different to + // the 8703 in Fragment class, so to distinguish how Fragment is initialized. + // actual value should be provided by symbol lookup Fragment(not yet created.) + .replace(R.id.container, OrderInputFragment.newInstance("8704")) + .commitNow() + } + } + +} diff --git a/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/DatePickerFragment.kt b/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/DatePickerFragment.kt new file mode 100644 index 0000000..5f7bcba --- /dev/null +++ b/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/DatePickerFragment.kt @@ -0,0 +1,32 @@ +package it.trade.android.japanapp.ui.orderinput + +import android.app.DatePickerDialog +import android.app.Dialog +import android.os.Bundle +import android.support.v4.app.DialogFragment +import android.util.Log +import android.widget.DatePicker +import java.util.* + +class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener { + + private lateinit var cb: (String) -> Unit + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val c = Calendar.getInstance() + val year = c.get(Calendar.YEAR) + val month = c.get(Calendar.MONTH) + val day = c.get(Calendar.DAY_OF_MONTH) + return DatePickerDialog(activity!!, this, year, month, day) + } + + fun setDateSetPickerCallBack(cb: (String) -> Unit) { + this.cb = cb + } + + override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) { + Log.d("OrderInputDatePicker", "picked a date: $year - ${month + 1} - $dayOfMonth") + cb(String.format("%d%02d%02d", year, month + 1, dayOfMonth)) + } +} + diff --git a/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/OrderInputFragment.kt b/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/OrderInputFragment.kt new file mode 100644 index 0000000..610ae4c --- /dev/null +++ b/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/OrderInputFragment.kt @@ -0,0 +1,242 @@ +package it.trade.android.japanapp.ui.orderinput + +import android.arch.lifecycle.Observer +import android.arch.lifecycle.ViewModelProviders +import android.os.Bundle +import android.support.v4.app.Fragment +import android.text.Editable +import android.text.TextWatcher +import android.util.Log +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.EditText +import android.widget.PopupMenu +import it.trade.android.japanapp.R +import kotlinx.android.synthetic.main.order_input_fragment.* + +private const val TAG = "OrderInputFragment" + +class OrderInputFragment : Fragment() { + + companion object { + fun newInstance(symbol: String): OrderInputFragment { + val args = Bundle() + args.putString("symbol", symbol) + val fragment = OrderInputFragment() + fragment.arguments = args + return fragment + } + } + + private lateinit var viewModel: OrderInputViewModel + private lateinit var symbol: String + private lateinit var accountAdapter: ArrayAdapter + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View { + symbol = arguments?.getString("symbol") ?: "8703" + return inflater.inflate(R.layout.order_input_fragment, container, false) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + viewModel = ViewModelProviders.of(activity!!, OrderInputViewModelFactory(symbol)).get(OrderInputViewModel::class.java) + viewModel.getOrderModel().observe(this, Observer { orderForm -> + orderForm?.run { + tvSymbolName.text = symbol.name + tvSymbol.text = "${symbol.symbol} ${symbol.exchange}" + tvCurrentTime.text = "13:00" + + tvPrice.text = String.format("%,.0f", symbol.price) + val change = String.format("%+,.0f", priceChange) + val percentage = String.format("%+.2f", priceChangePercentage * 100) + tvPriceChange.text = "$change ($percentage%)" + + tvBuyingPower.text = String.format("%,.0f", buyingPower.availableCash) + tvNisaLimit.text = String.format("(NISA) %,.0f", buyingPower.availableNisaLimit) + + etQuantity.setText(String.format("%d", orderInfo.quantity)) + etPrice.setText(String.format("%.0f", orderInfo.limitPrice)) + btMarket.isChecked = orderInfo.type == OrderType.MARKET + btLimit.isChecked = orderInfo.type == OrderType.LIMIT + + val lower = String.format("%,.0f", symbol.priceLowerLimit) + val upper = String.format("%,.0f", symbol.priceUpperLimit) + tvPriceLimit.text = "(値幅制限 $lower-$upper)" + val estimated = String.format("%,.0f", estimatedValue) + tvEstimatedValue.text = "$estimated 円" + + Log.d(TAG, "current expiry is ${orderInfo.expiry}") + btDay.isChecked = orderInfo.expiry == OrderExpiry.DAY + btWeek.isChecked = orderInfo.expiry == OrderExpiry.WEEK + btWeek.isEnabled = orderInfo.type == OrderType.LIMIT + btTillDate.isChecked = orderInfo.expiry == OrderExpiry.TILL_DATE + btTillDate.isEnabled = orderInfo.type == OrderType.LIMIT + btSession.isChecked = orderInfo.expiry in listOf(OrderExpiry.OPENING, OrderExpiry.CLOSING, OrderExpiry.FUNARI) + + val accountTypes = viewModel.getAvailabeAccountTypes() + accountAdapter.clear() + val selected = orderInfo.accountType + Log.d(TAG, "current account type: $selected") + for ((index, accountType) in accountTypes.withIndex()) { + when (accountType) { + AccountType.SPECIFIC -> accountAdapter.add(getString(R.string.specific)) + AccountType.GENERAL -> accountAdapter.add(getString(R.string.general)) + AccountType.NISA -> accountAdapter.add(getString(R.string.nisa)) + } + if (accountType == selected) spAccount.setSelection(index) + } + + } + }) + etQuantity.setOnTouchListener { v, event -> + val x = event?.x?.toInt()!! + val (start, _, end, _) = etQuantity.compoundDrawablesRelative + var processed = false + if (event.action == MotionEvent.ACTION_DOWN) { + when { + x <= (etQuantity.paddingStart + start.bounds.width()) -> { + viewModel.decreaseQuantity() + processed = true + } + x >= (etQuantity.right - end.bounds.width() - etQuantity.paddingEnd) -> { + viewModel.increaseQuantity() + processed = true + } + else -> v!!.performClick() + } + } + processed + } + etPrice.setOnTouchListener { v, event -> + val x = event?.x?.toInt()!! + val (start, _, end, _) = etPrice.compoundDrawablesRelative + var processed = false + if (event.action == MotionEvent.ACTION_DOWN) { + when { + x <= (etPrice.paddingStart + start.bounds.width()) -> { + viewModel.decreasePrice() + processed = true + } + x >= (etPrice.right - end.bounds.width() - etPrice.paddingEnd) -> { + viewModel.increasePrice() + processed = true + } + else -> v!!.performClick() + } + } + processed + } + btMarket.setOnClickListener { + viewModel.setMarketOrder() + togglePriceType() + } + btLimit.setOnClickListener { + viewModel.setLimitOrder() + togglePriceType() + } + etPrice.onChange { price -> + val selection = etPrice.selectionStart + val result = viewModel.setLimitPrice(price) + priceLayout.error = null + if (!result) { + priceLayout.error = getString(R.string.invalid_price) + } else if (selection >= 0) { + etPrice.setSelection(selection) + } + } + etQuantity.onChange { quantity -> + val selection = etQuantity.selectionStart + val result = viewModel.setQuantity(quantity) + quantityLayout.error = null + if (!result) { + quantityLayout.error = getString(R.string.invalid_quantity) + } else if (selection >= 0) { + etQuantity.setSelection(selection) + } + } + btDay.setOnClickListener { + viewModel.setExpiry(OrderExpiry.DAY) + } + btWeek.setOnClickListener { + viewModel.setExpiry(OrderExpiry.WEEK) + } + btTillDate.setOnClickListener { + btTillDate.isChecked = !btTillDate.isChecked + val datePicker = DatePickerFragment() + datePicker.setDateSetPickerCallBack { date -> + Log.d(TAG, "picked $date") + viewModel.setTillDate(date) + } + datePicker.show(activity!!.supportFragmentManager, "OrderInputDatePicker") + } + btSession.setOnClickListener { + // the button status should only updated by the viewModel instead of the click event + btSession.isChecked = !btSession.isChecked + val popup = PopupMenu(activity!!, it) + popup.inflate(R.menu.session_popup) + if (btMarket.isChecked) { + popup.menu.findItem(R.id.funari).isVisible = false + } + popup.setOnMenuItemClickListener { item -> + when (item?.itemId) { + R.id.opening -> { + viewModel.setExpiry(OrderExpiry.OPENING) + true + } + R.id.closing -> { + viewModel.setExpiry(OrderExpiry.CLOSING) + true + } + R.id.funari -> { + viewModel.setExpiry(OrderExpiry.FUNARI) + true + } + else -> false + } + } + popup.setOnDismissListener { _ -> viewModel.dummyUpdate() } + popup.show() + } + accountAdapter = ArrayAdapter(activity!!, android.R.layout.simple_spinner_item).apply { + setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + } + spAccount.adapter = accountAdapter + spAccount.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onNothingSelected(parent: AdapterView<*>?) {} + + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + viewModel.setAccountType(position) + } + + } + + } + + private fun togglePriceType() { + if (btLimit.isChecked) { + priceInput.visibility = View.VISIBLE + tvPriceLimit.visibility = View.VISIBLE + } else { + priceInput.visibility = View.GONE + tvPriceLimit.visibility = View.GONE + } + } + + private fun EditText.onChange(cb: (String) -> Unit) { + this.addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(s: Editable?) { + cb(s.toString()) + } + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} + }) + } + +} diff --git a/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/OrderInputViewModel.kt b/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/OrderInputViewModel.kt new file mode 100644 index 0000000..61e637d --- /dev/null +++ b/exampleAppJapan/src/main/kotlin/it/trade/android/japanapp/ui/orderinput/OrderInputViewModel.kt @@ -0,0 +1,234 @@ +package it.trade.android.japanapp.ui.orderinput + +import android.arch.lifecycle.LiveData +import android.arch.lifecycle.MutableLiveData +import android.arch.lifecycle.ViewModel +import android.arch.lifecycle.ViewModelProvider +import android.util.Log + +private const val TAG = "OrderInputViewModel" + +class OrderInputViewModel(private val symbol: String) : ViewModel() { + private lateinit var orderForm: MutableLiveData + + fun getOrderModel(): LiveData { + if (!this::orderForm.isInitialized) { + Log.d(TAG, "initialized.") + orderForm = MutableLiveData() + orderForm.value = OrderForm( + TradeItSDKHolder.getSymbolProvider().getJapanSymbol(symbol), + TradeItSDKHolder.getBuyingPower(), + TradeItSDKHolder.getAccountTypes()) + } + return orderForm + } + + fun getAvailabeAccountTypes():List { + // Japan user should always has a GENERAL account type + return orderForm.value?.availableAccounts ?: listOf(AccountType.GENERAL) + } + + fun increaseQuantity() { + orderForm.value = orderForm.value?.apply { + orderInfo = orderInfo.copy(quantity = orderInfo.quantity + symbol.lotSize) + } + } + + fun decreaseQuantity() { + val value = orderForm.value + if (value?.orderInfo?.quantity != value?.symbol?.lotSize) { + // do not decrease further when it's lotsize already + orderForm.value = value?.apply { + orderInfo = orderInfo.copy(quantity = orderInfo.quantity - symbol.lotSize) + } + } + } + + fun increasePrice() { + orderForm.value = orderForm.value?.apply { + if (orderInfo.limitPrice < symbol.priceUpperLimit) { + orderInfo = orderInfo.copy(limitPrice = orderInfo.limitPrice + 1) + } + } + } + + fun decreasePrice() { + orderForm.value = orderForm.value?.apply { + if (orderInfo.limitPrice > symbol.priceLowerLimit) { + orderInfo = orderInfo.copy(limitPrice = orderInfo.limitPrice - 1) + } + } + } + + fun setMarketOrder() { + orderForm.value = orderForm.value?.apply { + val expiry = if (orderInfo.expiry in listOf(OrderExpiry.WEEK, OrderExpiry.TILL_DATE, OrderExpiry.FUNARI)) + OrderExpiry.DAY + else + orderInfo.expiry + orderInfo = orderInfo.copy(type = OrderType.MARKET, limitPrice = symbol.price, expiry = expiry) + } + } + + fun setLimitOrder() { + orderForm.value = orderForm.value?.apply { + orderInfo = orderInfo.copy(type = OrderType.LIMIT) + } + } + + fun setLimitPrice(price: String): Boolean { + val newPrice = try { + price.toDouble() + } catch (e: NumberFormatException) { + return false + } + if (newPrice == orderForm.value?.orderInfo?.limitPrice) { + // to avoid infinite loop, don't update model when value is not actually updated + return true + } + var isValid = false + val newValue = orderForm.value?.apply { + if (newPrice >= symbol.priceLowerLimit && newPrice <= symbol.priceUpperLimit) { + orderInfo = orderInfo.copy(limitPrice = newPrice) + isValid = true + } + } + if (isValid) { + orderForm.value = newValue + } + return isValid + } + + fun setQuantity(quantity: String): Boolean { + val newQuantity = try { + quantity.toInt() + } catch (e: NumberFormatException) { + return false + } + if (newQuantity == orderForm.value?.orderInfo?.quantity) { + // to avoid infinite loop, don't update model when value is not actually updated + return true + } + var isValid = false + val newValue = orderForm.value?.apply { + if (newQuantity != 0 && newQuantity % symbol.lotSize == 0) { + orderInfo = orderInfo.copy(quantity = newQuantity) + isValid = true + } + } + if (isValid) { + orderForm.value = newValue + } + return isValid + } + + fun setExpiry(expiry: OrderExpiry) { + orderForm.value = orderForm.value?.apply { + orderInfo = orderInfo.copy(expiry = expiry) + } + } + + fun dummyUpdate() { + orderForm.value = orderForm.value + } + + fun setAccountType(position: Int) { + val accountType = getAvailabeAccountTypes()[position] + if (accountType != orderForm.value?.orderInfo?.accountType) { + orderForm.value = orderForm.value?.apply { + orderInfo = orderInfo.copy(accountType = accountType) + } + } + } + + fun setTillDate(date: String) { + orderForm.value = orderForm.value?.apply { + orderInfo = orderInfo.copy(expiry = OrderExpiry.TILL_DATE, expiryDate = date) + } + } +} + +class OrderInputViewModelFactory(private val symbol: String) : ViewModelProvider.NewInstanceFactory() { + override fun create(modelClass: Class): T { + @Suppress("UNCHECKED_CAST") + return OrderInputViewModel(symbol) as T + } + +} + +class OrderForm(val symbol: JapanSymbol, val buyingPower: BuyingPower, val availableAccounts: List) { + var orderInfo: OrderInfo = OrderInfo( + quantity = symbol.lotSize, + limitPrice = symbol.price, + type = OrderType.LIMIT, + expiry = OrderExpiry.DAY, + expiryDate = "", + accountType = AccountType.SPECIFIC + ) + + val estimatedValue: Double + get() { + return orderInfo.quantity * orderInfo.limitPrice + } + + val priceChange: Double + get() { + return symbol.price - symbol.previousDayPrice + } + + val priceChangePercentage: Double + get() { + return priceChange / symbol.previousDayPrice + } +} + +//TODO temp solutions below +interface JapanSymbolProvider { + fun getJapanSymbol(symbol: String): JapanSymbol +} + +class SampleJapanSymbol : JapanSymbolProvider { + override fun getJapanSymbol(symbol: String): JapanSymbol { + return JapanSymbol("カブドットコム証券(株)", + symbol, "東証1部", 386.0, + 384.0, 286.0, 486.0, 100) + } +} + +object TradeItSDKHolder { + fun getSymbolProvider(): JapanSymbolProvider { + return SampleJapanSymbol() + } + + fun getAccountTypes(): List { + return listOf(AccountType.SPECIFIC, AccountType.GENERAL, AccountType.NISA) + } + + // need broker/account + fun getBuyingPower(): BuyingPower { + return BuyingPower(500000.toDouble(), 100000.toDouble()) + } +} + +// TODO need to separate the price portion out +data class JapanSymbol(val name: String, val symbol: String, val exchange: String, + val price: Double, val previousDayPrice: Double, + val priceLowerLimit: Double, val priceUpperLimit: Double, + val lotSize: Int) + +data class OrderInfo(val quantity: Int, val limitPrice: Double, val type: OrderType, + val expiry: OrderExpiry, val expiryDate: String, val accountType: AccountType) + +data class BuyingPower(val availableCash: Double, val availableNisaLimit: Double) + +enum class OrderType { + LIMIT, MARKET +} + +enum class OrderExpiry { + DAY, WEEK, TILL_DATE, OPENING, CLOSING, FUNARI +} + +enum class AccountType { + SPECIFIC, GENERAL, NISA +} \ No newline at end of file diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/ic_arrow_drop_down.png b/exampleAppJapan/src/main/res/drawable-hdpi/ic_arrow_drop_down.png new file mode 100644 index 0000000..813f5bf Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/ic_arrow_drop_down.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/ic_arrow_drop_down_disabled.png b/exampleAppJapan/src/main/res/drawable-hdpi/ic_arrow_drop_down_disabled.png new file mode 100644 index 0000000..63476c1 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/ic_arrow_drop_down_disabled.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/ic_close_dark.png b/exampleAppJapan/src/main/res/drawable-hdpi/ic_close_dark.png new file mode 100644 index 0000000..5bd1b7c Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/ic_close_dark.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/ic_minus.png b/exampleAppJapan/src/main/res/drawable-hdpi/ic_minus.png new file mode 100644 index 0000000..20f9b0b Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/ic_minus.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/ic_minus_inactive.png b/exampleAppJapan/src/main/res/drawable-hdpi/ic_minus_inactive.png new file mode 100644 index 0000000..a95792b Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/ic_minus_inactive.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/ic_plus.png b/exampleAppJapan/src/main/res/drawable-hdpi/ic_plus.png new file mode 100644 index 0000000..5cba23b Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/ic_plus.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/ic_plus_inactive.png b/exampleAppJapan/src/main/res/drawable-hdpi/ic_plus_inactive.png new file mode 100644 index 0000000..303f7f8 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/ic_plus_inactive.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/panel_buy_done.png b/exampleAppJapan/src/main/res/drawable-hdpi/panel_buy_done.png new file mode 100644 index 0000000..7a01cbf Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/panel_buy_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/panel_sell_done.png b/exampleAppJapan/src/main/res/drawable-hdpi/panel_sell_done.png new file mode 100644 index 0000000..2e645e9 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/panel_sell_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_confirm.png b/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_confirm.png new file mode 100644 index 0000000..d40bc2c Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_confirm.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_done.png b/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_done.png new file mode 100644 index 0000000..059b862 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_input.png b/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_input.png new file mode 100644 index 0000000..f70512b Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/step_buy_input.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_confirm.png b/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_confirm.png new file mode 100644 index 0000000..6df5c3b Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_confirm.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_done.png b/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_done.png new file mode 100644 index 0000000..2c9b26f Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_input.png b/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_input.png new file mode 100644 index 0000000..9af8c1d Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-hdpi/step_sell_input.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/ic_arrow_drop_down.png b/exampleAppJapan/src/main/res/drawable-mdpi/ic_arrow_drop_down.png new file mode 100644 index 0000000..1c868d0 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/ic_arrow_drop_down.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/ic_arrow_drop_down_disabled.png b/exampleAppJapan/src/main/res/drawable-mdpi/ic_arrow_drop_down_disabled.png new file mode 100644 index 0000000..d421294 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/ic_arrow_drop_down_disabled.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/ic_close_dark.png b/exampleAppJapan/src/main/res/drawable-mdpi/ic_close_dark.png new file mode 100644 index 0000000..2854a94 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/ic_close_dark.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/ic_minus.png b/exampleAppJapan/src/main/res/drawable-mdpi/ic_minus.png new file mode 100644 index 0000000..769e974 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/ic_minus.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/ic_minus_inactive.png b/exampleAppJapan/src/main/res/drawable-mdpi/ic_minus_inactive.png new file mode 100644 index 0000000..124bbc7 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/ic_minus_inactive.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/ic_plus.png b/exampleAppJapan/src/main/res/drawable-mdpi/ic_plus.png new file mode 100644 index 0000000..2327b01 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/ic_plus.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/ic_plus_inactive.png b/exampleAppJapan/src/main/res/drawable-mdpi/ic_plus_inactive.png new file mode 100644 index 0000000..a4bf989 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/ic_plus_inactive.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/panel_buy_done.png b/exampleAppJapan/src/main/res/drawable-mdpi/panel_buy_done.png new file mode 100644 index 0000000..ceb3156 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/panel_buy_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/panel_sell_done.png b/exampleAppJapan/src/main/res/drawable-mdpi/panel_sell_done.png new file mode 100644 index 0000000..45789dd Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/panel_sell_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_confirm.png b/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_confirm.png new file mode 100644 index 0000000..ee2e3d1 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_confirm.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_done.png b/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_done.png new file mode 100644 index 0000000..47d0c78 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_input.png b/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_input.png new file mode 100644 index 0000000..1783d84 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/step_buy_input.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_confirm.png b/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_confirm.png new file mode 100644 index 0000000..129354c Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_confirm.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_done.png b/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_done.png new file mode 100644 index 0000000..ef40f80 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_input.png b/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_input.png new file mode 100644 index 0000000..edfac4a Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-mdpi/step_sell_input.png differ diff --git a/exampleAppJapan/src/main/res/drawable-v24/ic_launcher_foreground.xml b/exampleAppJapan/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/exampleAppJapan/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/ic_arrow_drop_down.png b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_arrow_drop_down.png new file mode 100644 index 0000000..8f528a5 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_arrow_drop_down.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/ic_arrow_drop_down_disabled.png b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_arrow_drop_down_disabled.png new file mode 100644 index 0000000..8979089 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_arrow_drop_down_disabled.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/ic_close_dark.png b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_close_dark.png new file mode 100644 index 0000000..fa23a22 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_close_dark.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/ic_minus.png b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_minus.png new file mode 100644 index 0000000..6148095 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_minus.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/ic_minus_inactive.png b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_minus_inactive.png new file mode 100644 index 0000000..cdf6f2f Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_minus_inactive.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/ic_plus.png b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_plus.png new file mode 100644 index 0000000..bf3e700 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_plus.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/ic_plus_inactive.png b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_plus_inactive.png new file mode 100644 index 0000000..5b66e6d Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/ic_plus_inactive.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/panel_buy_done.png b/exampleAppJapan/src/main/res/drawable-xhdpi/panel_buy_done.png new file mode 100644 index 0000000..e2ce536 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/panel_buy_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/panel_sell_done.png b/exampleAppJapan/src/main/res/drawable-xhdpi/panel_sell_done.png new file mode 100644 index 0000000..68f3349 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/panel_sell_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_confirm.png b/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_confirm.png new file mode 100644 index 0000000..bcd90f7 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_confirm.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_done.png b/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_done.png new file mode 100644 index 0000000..ea50fc9 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_input.png b/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_input.png new file mode 100644 index 0000000..b183abd Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/step_buy_input.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_confirm.png b/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_confirm.png new file mode 100644 index 0000000..d20c673 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_confirm.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_done.png b/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_done.png new file mode 100644 index 0000000..b6829b9 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_input.png b/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_input.png new file mode 100644 index 0000000..a447661 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xhdpi/step_sell_input.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png new file mode 100644 index 0000000..8bf3b74 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_arrow_drop_down_disabled.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_arrow_drop_down_disabled.png new file mode 100644 index 0000000..92a46b4 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_arrow_drop_down_disabled.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_close_dark.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_close_dark.png new file mode 100644 index 0000000..cffce20 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_close_dark.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_minus.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_minus.png new file mode 100644 index 0000000..3dac3d8 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_minus.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_minus_inactive.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_minus_inactive.png new file mode 100644 index 0000000..5257608 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_minus_inactive.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_plus.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_plus.png new file mode 100644 index 0000000..b2e2f38 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_plus.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_plus_inactive.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_plus_inactive.png new file mode 100644 index 0000000..e4eebe7 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/ic_plus_inactive.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/panel_buy_done.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/panel_buy_done.png new file mode 100644 index 0000000..17eb97e Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/panel_buy_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/panel_sell_done.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/panel_sell_done.png new file mode 100644 index 0000000..2856daf Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/panel_sell_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_confirm.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_confirm.png new file mode 100644 index 0000000..7f3247a Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_confirm.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_done.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_done.png new file mode 100644 index 0000000..532ac01 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_input.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_input.png new file mode 100644 index 0000000..28581f8 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_buy_input.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_confirm.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_confirm.png new file mode 100644 index 0000000..efed7f8 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_confirm.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_done.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_done.png new file mode 100644 index 0000000..6d0ba80 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_done.png differ diff --git a/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_input.png b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_input.png new file mode 100644 index 0000000..956adb4 Binary files /dev/null and b/exampleAppJapan/src/main/res/drawable-xxhdpi/step_sell_input.png differ diff --git a/exampleAppJapan/src/main/res/drawable/ic_launcher_background.xml b/exampleAppJapan/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/exampleAppJapan/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/exampleAppJapan/src/main/res/layout/main_activity.xml b/exampleAppJapan/src/main/res/layout/main_activity.xml new file mode 100644 index 0000000..c7ff3ba --- /dev/null +++ b/exampleAppJapan/src/main/res/layout/main_activity.xml @@ -0,0 +1,7 @@ + + diff --git a/exampleAppJapan/src/main/res/layout/order_input_fragment.xml b/exampleAppJapan/src/main/res/layout/order_input_fragment.xml new file mode 100644 index 0000000..23d5998 --- /dev/null +++ b/exampleAppJapan/src/main/res/layout/order_input_fragment.xml @@ -0,0 +1,456 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +